diff --git a/.cirrus.yml b/.cirrus.yml index fa6952e8..3b3aa09a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,12 +1,12 @@ +# SPDX-License-Identifier: MPL-2.0 task: name: FreeBSD env: - GITHUB_TOKEN: ENCRYPTED[!9dec9949a2f8e3df89062aa2eaee35279bf7c62a43f6e8a5a4407cde75f05f48ffdb157363d0090a91616da307c71832!] + GITHUB_TOKEN: ENCRYPTED[!ee1c9f1da9e4736edb4f543b3d2431949b17e6a86877e95ca4323f677185f7fbaae52c6afeb8145f0735bad487291a27!] freebsd_instance: matrix: - image_family: freebsd-14-0 - image_family: freebsd-13-2 - image_family: freebsd-12-4 + image_family: freebsd-14-1 + image_family: freebsd-13-3 install_script: pkg install -y git meson submodules_script: git submodule update --init --recursive --progress release_script: | diff --git a/.gitattributes b/.gitattributes index 7278b224..b1d07ddd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 #this file specifies some rules on specific files for line endings and more. #it also has a section on which files should NOT be part of an export (git archive) command. diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index d80da831..c8bcf6d8 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 name: C/C++ CI on: @@ -37,7 +38,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive @@ -69,12 +70,13 @@ jobs: ${{ matrix.config.archive_command }} "${DESTDIR}${ARCHIVE_EXT}" ../${{ matrix.config.builddir }}/openseachest_exes - name: Uploading artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: ${{ format('{0}', env.DESTDIR) }} path: ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} # - name: Publish release # if: ${{ startsWith(github.ref, 'refs/tags/v') && matrix.config.publish_release }} - # uses: softprops/action-gh-release@v1 + # uses: softprops/action-gh-release@v2 # with: # files: ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0c6342b0..1362c8ea 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 # For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # @@ -17,8 +18,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-latest - + runs-on: ${{ matrix.config.os }} strategy: fail-fast: false matrix: @@ -27,15 +27,50 @@ jobs: language: ['cpp'] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + config: + - { + name: "Windows MSVC x64", + os: windows-latest, + cc: "cl.exe", + cxx: "cl.exe", + arch: "x64", + meson_opts: "-Db_vscrt=static_from_buildtype" + } + - { + name: "Windows MSVC x86", + os: windows-latest, + cc: "cl.exe", + cxx: "cl.exe", + arch: "x64_x86", + meson_opts: "-Db_vscrt=static_from_buildtype" + } + - { + name: "Ubuntu GCC", + os: ubuntu-latest, + cc: "gcc", + cxx: "g++" + } + - { + name: "Ubuntu Clang", + os: ubuntu-latest, + cc: "clang", + cxx: "clang++" + } steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 submodules: recursive + + - name: Settings vars for MSVC + if: startsWith(matrix.config.name, 'Windows MSVC') + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.config.arch }} # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. @@ -44,7 +79,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -65,11 +100,12 @@ jobs: # uses a compiled language - name: Configuring and compiling with meson - uses: BSFishy/meson-build@v1.0.3 - with: - action: build - options: --verbose - meson-version: 0.60.1 + env: + CC: ${{ matrix.config.cc }} + CXX: ${{ matrix.config.cxx }} + run: | + pip install meson ninja + meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml index 7078a5f6..444c8dcd 100644 --- a/.github/workflows/meson.yml +++ b/.github/workflows/meson.yml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 name: CI for meson build on: @@ -40,6 +41,18 @@ jobs: release_extension: ".zip", archive_command: "7z a -tzip -mmt" } + - { + name: "Windows MSVC ARM64", + os: windows-latest, + cc: "cl.exe", + cxx: "cl.exe", + arch: "x64_arm64", + publish_release: true, + meson_opts: "-Db_vscrt=static_from_buildtype --cross-file=./meson_crosscompile/msvc_arm64.txt", + release_name: "win-ARM64", + release_extension: ".zip", + archive_command: "7z a -tzip -mmt" + } - { name: "Windows GCC", os: windows-latest, @@ -54,6 +67,7 @@ jobs: os: windows-latest, cc: "clang.exe", cxx: "clang++.exe", + meson_opts: "--native-file=./meson_crosscompile/Windows-Clang.txt", release_name: "win-x86_64-clang", release_extension: ".zip", archive_command: "7z a -tzip -mmt" @@ -76,24 +90,13 @@ jobs: release_extension: ".tar.xz", archive_command: "tar cvfJ" } - - { - name: "Manylinux GCC", - os: ubuntu-latest, - image: "quay.io/pypa/manylinux2014_x86_64", - cc: "gcc", - cxx: "g++", - publish_release: true, - create_package: true, - release_name: "linux-x86_64-manylinux", - release_extension: ".tar.xz", - archive_command: "tar cvfJ" - } - { name: "MUSL Cross Compile x86_64", os: ubuntu-latest, cc: "", cxx: "", publish_release: true, + create_package: true, meson_opts: "--cross-file=./meson_crosscompile/x86_64-linux-musl-cross.txt", cross_compiler_arch: "x86_64", release_name: "linux-x86_64-portable", @@ -184,9 +187,24 @@ jobs: release_extension: ".tar.xz", archive_command: "tar cvfJ" } + outputs: #where hashes need to be stored for slsa provenance + #NOTE: Only doing this for builds with "publish_release: true" + #format is hash-${{release_name}} for the zipped packages + # + hash-win-x64: ${{ steps.hash.outputs.hash-win-x64 }} + hash-win-x86: ${{ steps.hash.outputs.hash-win-x86 }} + hash-win-ARM64: ${{ steps.hash.outputs.hash-win-ARM64 }} + hash-linux-x86_64-portable: ${{ steps.hash.outputs.hash-linux-x86_64-portable }} + hash-linux-i686-portable: ${{ steps.hash.outputs.hash-linux-i686-portable }} + hash-linux-aarch64-portable: ${{ steps.hash.outputs.hash-linux-aarch64-portable }} + hash-linux-armv7l-portable: ${{ steps.hash.outputs.hash-linux-armv7l-portable }} + hash-linux-armv6-portable: ${{ steps.hash.outputs.hash-linux-armv6-portable }} + hash-linux-armv5l-portable: ${{ steps.hash.outputs.hash-linux-armv5l-portable }} + hash-linux-powerpc64-portable: ${{ steps.hash.outputs.hash-linux-powerpc64-portable }} + hash-linux-powerpc64le-portable: ${{ steps.hash.outputs.hash-linux-powerpc64le-portable }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive @@ -210,7 +228,7 @@ jobs: - name: Restore LLVM from cache if: startsWith(matrix.config.name, 'Windows Clang') id: llvm-cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: C:/Program Files/LLVM key: 'llvm-llvm-project-relid-${{ env.LLVM_RELID }}' @@ -222,13 +240,6 @@ jobs: Invoke-WebRequest -Headers $headers -OutFile "LLVM.exe" ((Invoke-WebRequest -Headers $headers "https://api.github.com/repos/llvm/llvm-project/releases/$($env:LLVM_RELID)").Content | ConvertFrom-Json | Select-Object -ExpandProperty assets | Where -Property name -Like "*win64.exe" | Select-Object -First 1).browser_download_url 7z x LLVM.exe -y -o"C:/Program Files/LLVM" - - name: Setup toolchain for Manylinux - if: ${{ matrix.config.image == 'quay.io/pypa/manylinux2014_x86_64' }} - shell: bash - run: | - if [[ ${{ matrix.config.cc }} == "clang" ]] ; then yum install -y clang compat-gcc-44 ; fi - echo "/opt/python/cp310-cp310/bin" >> $GITHUB_PATH - - name: Escape backslash in branch name shell: bash run: echo "BRANCH_NAME=$(echo ${{ github.ref_name }} | tr / -)" >> $GITHUB_ENV @@ -245,7 +256,7 @@ jobs: CC: ${{ matrix.config.cc }} CXX: ${{ matrix.config.cxx }} run: | - pip install meson==0.60.3 ninja + pip install meson ninja meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release meson install -C build @@ -258,16 +269,17 @@ jobs: shell: bash # add `GOBIN` to the `PATH` otherwise nfpm in next step can't be found - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v5 if: ${{ matrix.config.create_package }} with: go-version: 'stable' + cache: false - name: Create packages if: ${{ matrix.config.create_package }} working-directory: ${{ format('build/{0}', env.DESTDIR) }} run: | # https://nfpm.goreleaser.com/install/ - go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.22.2 + go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.36.1 if [[ ${{ github.ref }} =~ ^refs/tags/v[0-9\.]+$ ]]; then version=$(echo ${{ github.ref_name }} | tr -d 'v') else @@ -278,9 +290,24 @@ jobs: nfpm package -f ../../nfpm.yaml -p rpm -t .. shell: bash + - name: Generate Hashes + if: ${{ matrix.config.publish_release }} + shell: bash + id: hash + run: | + # sha256sum generates sha256 hash for all artifacts. + # base64 -w0 encodes to base64 and outputs on a single line. + # sha256sum artifact | base64 -w0 + # NOTE: Using suggested method to generate sha across OS's from slsa documentation + # https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/generic/README.md#provenance-for-artifacts-built-across-multiple-operating-systems + set -euo pipefail + (sha256sum -t ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} || shasum -a 256 ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }}) > checksum + echo "hash-${{ matrix.config.release_name }}=$(base64 -w0 checksum || base64 checksum)" >> "${GITHUB_OUTPUT}" + - name: Uploading artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: ${{ format('{0}', matrix.config.release_name) }} path: | ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} build/*.deb @@ -288,9 +315,36 @@ jobs: - name: Publish release if: ${{ startsWith(github.ref, 'refs/tags/v') && matrix.config.publish_release }} - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: | ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} build/*.deb build/*.rpm + + # This step takes all the generated hashes from all build targets and combines them so slsa provenance step can run + combine_hashes: + runs-on: ubuntu-latest + needs: [build] + outputs: + hashes: ${{ steps.hashes.outputs.hashes }} + env: + HASHES: ${{ toJSON(needs.build.outputs) }} + steps: + - id: hashes + run: | + echo "$HASHES" + echo "$HASHES" | jq -r '.[] | @base64d' | sed "/^$/d" > hashes.txt + echo "hashes=$(cat hashes.txt | base64 -w0)" >> "$GITHUB_OUTPUT" + + # Generate the slsa provenance + provenance: + needs: [combine_hashes] + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 + with: + base64-subjects: "${{ needs.combine_hashes.outputs.hashes }}" + upload-assets: true # Optional: Upload to a new release diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 6e031623..c4fa47e7 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 name: MSBuild on: @@ -23,41 +24,26 @@ env: jobs: build: - runs-on: windows-2019 # Windows latest is now Win11, which codeQL will not run on + runs-on: windows-latest strategy: matrix: platform: [ x64, x86 ] language: ['cpp'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive - name: Add MSBuild to PATH - uses: microsoft/setup-msbuild@v1 + uses: microsoft/setup-msbuild@v2 - name: Restore NuGet packages working-directory: ${{env.GITHUB_WORKSPACE}} run: nuget restore ${{env.SOLUTION_FILE_PATH}} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - if: ${{ startsWith(github.ref, 'refs/heads/develop') || startsWith(github.ref, 'refs/heads/master') }} - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - name: Build working-directory: ${{env.GITHUB_WORKSPACE}} # Add additional options to the MSBuild command line here (like platform or verbosity level). # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} /p:Platform=${{matrix.platform}} - - - name: Perform CodeQL Analysis - if: ${{ startsWith(github.ref, 'refs/heads/develop') || startsWith(github.ref, 'refs/heads/master') }} - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/source-release.yml b/.github/workflows/source-release.yml index 942d5fcb..33b04e7e 100644 --- a/.github/workflows/source-release.yml +++ b/.github/workflows/source-release.yml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 name: Create Complete Source Archive on: @@ -22,8 +23,13 @@ jobs: os: ubuntu-latest, extension: ".tar.xz", } + outputs: + #store hashes for slsa provenance + hash-SourceCode_With_Submodules-Windows: ${{ steps.hash.outputs.hash-SourceCode_With_Submodules-Windows }} + hash-SourceCode_With_Submodules-Linux: ${{ steps.hash.outputs.hash-SourceCode_With_Submodules-Linux }} + steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive @@ -41,15 +47,47 @@ jobs: - name: Create Source Archive run: | pip install git-archive-all - git-archive-all --prefix=${{ env.ARCHIVENAME }} SourceCode_With_Submodules.${{ matrix.config.extension }} + git-archive-all --prefix=${{ env.ARCHIVENAME }} SourceCode_With_Submodules${{ matrix.config.extension }} + + - name: Generate Hashes + shell: bash + id: hash + run: | + # sha256sum generates sha256 hash for all artifacts. + # base64 -w0 encodes to base64 and outputs on a single line. + # sha256sum artifact | base64 -w0 + # NOTE: Using suggested method to generate sha across OS's from slsa documentation + # https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/generic/README.md#provenance-for-artifacts-built-across-multiple-operating-systems + set -euo pipefail + (sha256sum -t ${{ format('SourceCode_With_Submodules{0}', matrix.config.extension) }} || shasum -a 256 ${{ format('SourceCode_With_Submodules{0}', matrix.config.extension) }}) > checksum + echo "hash-SourceCode_With_Submodules-${{ matrix.config.name }}=$(base64 -w0 checksum || base64 checksum)" >> "${GITHUB_OUTPUT}" - name: Upload Source Archive as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - path: SourceCode_With_Submodules.${{ matrix.config.extension }} + name: SourceCode_With_Submodules-${{ matrix.config.name }} + path: SourceCode_With_Submodules${{ matrix.config.extension }} - name: Publish Source Archive to Release if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: - files: SourceCode_With_Submodules.${{ matrix.config.extension }} + files: SourceCode_With_Submodules${{ matrix.config.extension }} + + # Generate the slsa provenance + provenance: + needs: [archive] + strategy: + fail-fast: false #don't cancel other jobs if one is failing + matrix: + package_name: [ "SourceCode_With_Submodules-Windows", + "SourceCode_With_Submodules-Linux" ] + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 + with: + base64-subjects: "${{ needs.archive.outputs[format('hash-{0}', matrix.package_name)] }}" + # Upload provenance to a new release + upload-assets: true diff --git a/.gitignore b/.gitignore index 35d10550..d3c478b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## diff --git a/.gitmodules b/.gitmodules index 91a55378..75f3f8f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 [submodule "opensea-common"] path = subprojects/opensea-common url = https://github.com/Seagate/opensea-common.git diff --git a/.whitesource b/.whitesource index e0aaa3e9..0075025a 100644 --- a/.whitesource +++ b/.whitesource @@ -1,8 +1,9 @@ { - "checkRunSettings": { - "vulnerableCheckRunConclusionLevel": "failure" + "settingsInheritedFrom": "Seagate/whitesource-config@main", + "scanSettings": { + "configMode": "LOCAL" }, - "issueSettings": { - "minSeverityLevel": "LOW" + "scanSettingsSAST": { + "baseBranches": [ "develop" ] } } \ No newline at end of file diff --git a/Make/UEFI/copy_files.sh b/Make/UEFI/copy_files.sh index 3d848d22..da64a081 100755 --- a/Make/UEFI/copy_files.sh +++ b/Make/UEFI/copy_files.sh @@ -1,5 +1,5 @@ #!/bin/bash - +# SPDX-License-Identifier: MPL-2.0 function usage { echo "This script will copy all files required to build openSeaChest to the edk2/UDK path specified." echo "Once the script is done copying, change the target.txt to build one of the following:" diff --git a/Make/UEFI/openSeaChestPkg.dec b/Make/UEFI/openSeaChestPkg.dec index 52e7084d..41e31fae 100644 --- a/Make/UEFI/openSeaChestPkg.dec +++ b/Make/UEFI/openSeaChestPkg.dec @@ -1,5 +1,5 @@ ## @file - +# SPDX-License-Identifier: MPL-2.0 ## diff --git a/Make/UEFI/openSeaChestPkg.dsc b/Make/UEFI/openSeaChestPkg.dsc index e9c4fa7f..56915b93 100644 --- a/Make/UEFI/openSeaChestPkg.dsc +++ b/Make/UEFI/openSeaChestPkg.dsc @@ -8,6 +8,7 @@ # environment. # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] PLATFORM_NAME = openSeaChestPkg diff --git a/Make/UEFI/openSeaChest_Basics.inf b/Make/UEFI/openSeaChest_Basics.inf index 3ccd55a3..c723c797 100644 --- a/Make/UEFI/openSeaChest_Basics.inf +++ b/Make/UEFI/openSeaChest_Basics.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Configure.inf b/Make/UEFI/openSeaChest_Configure.inf index 82a6a9df..047aafd0 100644 --- a/Make/UEFI/openSeaChest_Configure.inf +++ b/Make/UEFI/openSeaChest_Configure.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Erase.inf b/Make/UEFI/openSeaChest_Erase.inf index c2170a6b..17ad0b6b 100644 --- a/Make/UEFI/openSeaChest_Erase.inf +++ b/Make/UEFI/openSeaChest_Erase.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Firmware.inf b/Make/UEFI/openSeaChest_Firmware.inf index 2f2ec61f..b60eb94d 100644 --- a/Make/UEFI/openSeaChest_Firmware.inf +++ b/Make/UEFI/openSeaChest_Firmware.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Format.inf b/Make/UEFI/openSeaChest_Format.inf index 5e40c511..6f3f05a1 100644 --- a/Make/UEFI/openSeaChest_Format.inf +++ b/Make/UEFI/openSeaChest_Format.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_GenericTests.inf b/Make/UEFI/openSeaChest_GenericTests.inf index 31c3377f..89be1625 100644 --- a/Make/UEFI/openSeaChest_GenericTests.inf +++ b/Make/UEFI/openSeaChest_GenericTests.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Info.inf b/Make/UEFI/openSeaChest_Info.inf index feff0572..b0600a86 100644 --- a/Make/UEFI/openSeaChest_Info.inf +++ b/Make/UEFI/openSeaChest_Info.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Logs.inf b/Make/UEFI/openSeaChest_Logs.inf index 099ca761..c319bf3c 100644 --- a/Make/UEFI/openSeaChest_Logs.inf +++ b/Make/UEFI/openSeaChest_Logs.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_NVMe.inf b/Make/UEFI/openSeaChest_NVMe.inf index f4e40b8f..184279f4 100644 --- a/Make/UEFI/openSeaChest_NVMe.inf +++ b/Make/UEFI/openSeaChest_NVMe.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_PowerControl.inf b/Make/UEFI/openSeaChest_PowerControl.inf index 8429a15c..5ea06b5d 100644 --- a/Make/UEFI/openSeaChest_PowerControl.inf +++ b/Make/UEFI/openSeaChest_PowerControl.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_SMART.inf b/Make/UEFI/openSeaChest_SMART.inf index 1fd696a0..cc79cd84 100644 --- a/Make/UEFI/openSeaChest_SMART.inf +++ b/Make/UEFI/openSeaChest_SMART.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Sample.inf b/Make/UEFI/openSeaChest_Sample.inf index 9ea29497..0b35a90e 100644 --- a/Make/UEFI/openSeaChest_Sample.inf +++ b/Make/UEFI/openSeaChest_Sample.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_Security.inf b/Make/UEFI/openSeaChest_Security.inf index 086caf7a..994912dc 100644 --- a/Make/UEFI/openSeaChest_Security.inf +++ b/Make/UEFI/openSeaChest_Security.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/UEFI/openSeaChest_ZBD.inf b/Make/UEFI/openSeaChest_ZBD.inf index 44e61c35..28004969 100644 --- a/Make/UEFI/openSeaChest_ZBD.inf +++ b/Make/UEFI/openSeaChest_ZBD.inf @@ -3,6 +3,7 @@ # # ## +# SPDX-License-Identifier: MPL-2.0 [Defines] INF_VERSION = 0x00010006 diff --git a/Make/VS.2019/OpenSeaChest.sln b/Make/VS.2019/OpenSeaChest.sln index 729cf4a5..cecbe0c5 100644 --- a/Make/VS.2019/OpenSeaChest.sln +++ b/Make/VS.2019/OpenSeaChest.sln @@ -157,6 +157,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenSeaChest_Reservations", {FBCBA2F1-3BF8-4A25-B815-E228E1AEDCFF} = {FBCBA2F1-3BF8-4A25-B815-E228E1AEDCFF} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenSeaChest_Raw", "OpenSeaChest_Raw\OpenSeaChest_Raw.vcxproj", "{A275B070-D641-414D-AE6A-7796F6D6BE2A}" + ProjectSection(ProjectDependencies) = postProject + {7DAC7F63-E808-47FD-BEEB-33E4A870008B} = {7DAC7F63-E808-47FD-BEEB-33E4A870008B} + {A0771494-8717-48AB-A0E5-49191252FF2C} = {A0771494-8717-48AB-A0E5-49191252FF2C} + {621B44CE-B314-4E05-B214-5DC70F2B4798} = {621B44CE-B314-4E05-B214-5DC70F2B4798} + {FBCBA2F1-3BF8-4A25-B815-E228E1AEDCFF} = {FBCBA2F1-3BF8-4A25-B815-E228E1AEDCFF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openSeaChest_Defect", "openSeaChest_Defect\openSeaChest_Defect.vcxproj", "{2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}" + ProjectSection(ProjectDependencies) = postProject + {7DAC7F63-E808-47FD-BEEB-33E4A870008B} = {7DAC7F63-E808-47FD-BEEB-33E4A870008B} + {A0771494-8717-48AB-A0E5-49191252FF2C} = {A0771494-8717-48AB-A0E5-49191252FF2C} + {621B44CE-B314-4E05-B214-5DC70F2B4798} = {621B44CE-B314-4E05-B214-5DC70F2B4798} + {FBCBA2F1-3BF8-4A25-B815-E228E1AEDCFF} = {FBCBA2F1-3BF8-4A25-B815-E228E1AEDCFF} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -865,6 +881,62 @@ Global {926C8C5D-B6E6-4516-836F-70F9488378A1}.Static-Release|x64.Build.0 = Static-Release|x64 {926C8C5D-B6E6-4516-836F-70F9488378A1}.Static-Release|x86.ActiveCfg = Static-Release|Win32 {926C8C5D-B6E6-4516-836F-70F9488378A1}.Static-Release|x86.Build.0 = Static-Release|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Debug|ARM.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Debug|ARM64.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Debug|x64.ActiveCfg = Debug|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Debug|x64.Build.0 = Debug|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Debug|x86.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Debug|x86.Build.0 = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Release|ARM.ActiveCfg = Release|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Release|ARM64.ActiveCfg = Release|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Release|x64.ActiveCfg = Release|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Release|x64.Build.0 = Release|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Release|x86.ActiveCfg = Release|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Release|x86.Build.0 = Release|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|ARM.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|ARM.Build.0 = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|ARM64.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|ARM64.Build.0 = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|x64.ActiveCfg = Debug|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|x64.Build.0 = Debug|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|x86.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Debug|x86.Build.0 = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|ARM.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|ARM.Build.0 = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|ARM64.ActiveCfg = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|ARM64.Build.0 = Debug|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|x64.ActiveCfg = Release|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|x64.Build.0 = Release|x64 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|x86.ActiveCfg = Release|Win32 + {A275B070-D641-414D-AE6A-7796F6D6BE2A}.Static-Release|x86.Build.0 = Release|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Debug|ARM.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Debug|ARM64.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Debug|x64.ActiveCfg = Debug|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Debug|x64.Build.0 = Debug|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Debug|x86.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Debug|x86.Build.0 = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Release|ARM.ActiveCfg = Release|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Release|ARM64.ActiveCfg = Release|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Release|x64.ActiveCfg = Release|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Release|x64.Build.0 = Release|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Release|x86.ActiveCfg = Release|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Release|x86.Build.0 = Release|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|ARM.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|ARM.Build.0 = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|ARM64.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|ARM64.Build.0 = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|x64.ActiveCfg = Debug|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|x64.Build.0 = Debug|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|x86.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Debug|x86.Build.0 = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|ARM.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|ARM.Build.0 = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|ARM64.ActiveCfg = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|ARM64.Build.0 = Debug|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|x64.ActiveCfg = Release|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|x64.Build.0 = Release|x64 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|x86.ActiveCfg = Release|Win32 + {2A5F37B2-60C0-4CCD-B43A-71FC72923ACB}.Static-Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Make/VS.2019/OpenSeaChest_Raw/OpenSeaChest_Raw.vcxproj b/Make/VS.2019/OpenSeaChest_Raw/OpenSeaChest_Raw.vcxproj new file mode 100644 index 00000000..e24ab886 --- /dev/null +++ b/Make/VS.2019/OpenSeaChest_Raw/OpenSeaChest_Raw.vcxproj @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" 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>16.0</VCProjectVersion> + <Keyword>Win32Proj</Keyword> + <ProjectGuid>{a275b070-d641-414d-ae6a-7796f6d6be2a}</ProjectGuid> + <RootNamespace>OpenSeaChestRaw</RootNamespace> + <WindowsTargetPlatformVersion>10.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>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</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|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(Platform)\$(Configuration)\</IntDir> + <TargetName>openSeaChest_Raw</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(Platform)\$(Configuration)\</IntDir> + <TargetName>openSeaChest_Raw</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <TargetName>openSeaChest_Raw</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <TargetName>openSeaChest_Raw</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\..\..\include\EULA.h" /> + <ClInclude Include="..\..\..\include\openseachest_util_options.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\src\EULA.c" /> + <ClCompile Include="..\..\..\src\openseachest_util_options.c" /> + <ClCompile Include="..\..\..\utils\C\openSeaChest\openSeaChest_Raw.c" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Make/VS.2019/OpenSeaChest_Raw/OpenSeaChest_Raw.vcxproj.filters b/Make/VS.2019/OpenSeaChest_Raw/OpenSeaChest_Raw.vcxproj.filters new file mode 100644 index 00000000..de3abda8 --- /dev/null +++ b/Make/VS.2019/OpenSeaChest_Raw/OpenSeaChest_Raw.vcxproj.filters @@ -0,0 +1,36 @@ +<?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;c++;cppm;ixx;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;h++;hm;inl;inc;ipp;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="..\..\..\include\EULA.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\include\openseachest_util_options.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\src\EULA.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\src\openseachest_util_options.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\utils\C\openSeaChest\openSeaChest_Raw.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Make/VS.2019/openSeaChest_Defect/openSeaChest_Defect.vcxproj b/Make/VS.2019/openSeaChest_Defect/openSeaChest_Defect.vcxproj new file mode 100644 index 00000000..3b6db090 --- /dev/null +++ b/Make/VS.2019/openSeaChest_Defect/openSeaChest_Defect.vcxproj @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" 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>16.0</VCProjectVersion> + <Keyword>Win32Proj</Keyword> + <ProjectGuid>{2a5f37b2-60c0-4ccd-b43a-71fc72923acb}</ProjectGuid> + <RootNamespace>openSeaChestDefect</RootNamespace> + <WindowsTargetPlatformVersion>10.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>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</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|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + <TargetName>openSeaChest_Defect</TargetName> + <IntDir>$(Platform)\$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + <TargetName>openSeaChest_Defect</TargetName> + <IntDir>$(Platform)\$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <TargetName>openSeaChest_Defect</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <TargetName>openSeaChest_Defect</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>EnableAllWarnings</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>STATIC_OPENSEA_TRANSPORT;STATIC_OPENSEA_OPERATIONS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;ENABLE_CSMI;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard_C>stdc17</LanguageStandard_C> + <AdditionalIncludeDirectories>..\..\..\subprojects\opensea-transport\include;..\..\..\subprojects\opensea-operations\include;..\..\..\include;..\..\..\subprojects\opensea-common\include;..\..\..\subprojects\wingetopt\src;..\..\..\subprojects\opensea-transport\include\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DiagnosticsFormat>Caret</DiagnosticsFormat> + <CompileAs>CompileAsC</CompileAs> + <DisableSpecificWarnings>4214;4201;4668;4820;4710;4255;5045;4711;4324;4221;4204;4061;5105</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>..\..\..\subprojects\opensea-transport\Make\VS.2019\opensea-transport\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\opensea-operations\Make\VS.2019\opensea-operations\$(Platform)\$(Configuration)\LIB;..\..\..\subprojects\wingetopt\VS.2019\$(Platform)\$(Configuration);..\..\..\subprojects\opensea-common\Make\VS.2019\opensea-common\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>opensea-common.lib;opensea-transport.lib;opensea-operations.lib;getopt.lib;%(AdditionalDependencies)</AdditionalDependencies> + <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <MinimumRequiredVersion>6.0</MinimumRequiredVersion> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\..\..\include\EULA.h" /> + <ClInclude Include="..\..\..\include\openseachest_util_options.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\src\EULA.c" /> + <ClCompile Include="..\..\..\src\openseachest_util_options.c" /> + <ClCompile Include="..\..\..\utils\C\openSeaChest\openSeaChest_Defect.c" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Make/VS.2019/openSeaChest_Defect/openSeaChest_Defect.vcxproj.filters b/Make/VS.2019/openSeaChest_Defect/openSeaChest_Defect.vcxproj.filters new file mode 100644 index 00000000..30bcaf22 --- /dev/null +++ b/Make/VS.2019/openSeaChest_Defect/openSeaChest_Defect.vcxproj.filters @@ -0,0 +1,36 @@ +<?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;c++;cppm;ixx;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;h++;hm;inl;inc;ipp;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="..\..\..\include\EULA.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\include\openseachest_util_options.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\src\EULA.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\src\openseachest_util_options.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\utils\C\openSeaChest\openSeaChest_Defect.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/Make/gcc/Makefile b/Make/gcc/Makefile index 51d26703..173e9db3 100644 --- a/Make/gcc/Makefile +++ b/Make/gcc/Makefile @@ -1,7 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 # # Do NOT modify or remove this copyright and license # -# Copyright (c) 2012 - 2019 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# Copyright (c) 2012-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved # # This software is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Make/gccWin/Makefile.gccWin b/Make/gccWin/Makefile.gccWin index 0ecbad5e..fa7f6eaf 100644 --- a/Make/gccWin/Makefile.gccWin +++ b/Make/gccWin/Makefile.gccWin @@ -1,7 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 # # Do NOT modify or remove this copyright and license # -# Copyright (c) 2012 - 2019 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# Copyright (c) 2012-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved # # This software is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Make/gccWin/rename_seachest.sh b/Make/gccWin/rename_seachest.sh index b44deebd..c9213d18 100755 --- a/Make/gccWin/rename_seachest.sh +++ b/Make/gccWin/rename_seachest.sh @@ -1,4 +1,5 @@ #!/bin/bash +# SPDX-License-Identifier: MPL-2.0 # #=============== Global Variables ============================================ # Date last edit diff --git a/Make/vmware/Makefile b/Make/vmware/Makefile index 7d5164f8..7e1c8ff4 100644 --- a/Make/vmware/Makefile +++ b/Make/vmware/Makefile @@ -1,7 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 # # Do NOT modify or remove this copyright and license # -# Copyright (c) 2012 - 2017 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# Copyright (c) 2012-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved # # This software is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Make/vmware/Makefile.openSeaChest_firmware b/Make/vmware/Makefile.openSeaChest_firmware index 33ea9631..dd92b9a7 100644 --- a/Make/vmware/Makefile.openSeaChest_firmware +++ b/Make/vmware/Makefile.openSeaChest_firmware @@ -1,7 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 # # Do NOT modify or remove this copyright and license # -# Copyright (c) 2012 - 2017 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# Copyright (c) 2012-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved # # This software is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/README.md b/README.md index 9d415cf0..772fc301 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Cross platform utilities useful for performing various operations on SATA, SAS, NVMe, and USB storage devices -### Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +### Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved [](https://github.com/Seagate/openSeaChest/actions/workflows/msbuild.yml) [](https://github.com/Seagate/openSeaChest/actions/workflows/codeql-analysis.yml) diff --git a/cirrus_ci_post_freebsd_release.sh b/cirrus_ci_post_freebsd_release.sh index 938547aa..9aa3dff4 100755 --- a/cirrus_ci_post_freebsd_release.sh +++ b/cirrus_ci_post_freebsd_release.sh @@ -1,5 +1,7 @@ #!/bin/sh +# SPDX-License-Identifier: MPL-2.0 + #This script is based on the original example found here: https://cirrus-ci.org/examples/#release-assets #modifications made to upload only the single artificate necessary from each freeBSD build of #openSeaChest. This script should be run after the tar.xz file is created by a successful build @@ -61,4 +63,4 @@ if [ -f "$file_to_upload" ]; then else echo "tar file not found. Nothing to upload!" -fi \ No newline at end of file +fi diff --git a/docs/man/man8/openSeaChest_Basics.8 b/docs/man/man8/openSeaChest_Basics.8 index fac966d6..03fd5ca3 100644 --- a/docs/man/man8/openSeaChest_Basics.8 +++ b/docs/man/man8/openSeaChest_Basics.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Basics:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_BASICS "1" "August 2024" "openSeaChest_Basics ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Basics \- manual page for openSeaChest_Basics ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Basics \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Basics Version: 3.5.4\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:13 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Basics Version: 3.6.2\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user .PP ========================================================================================== Usage @@ -50,7 +50,9 @@ openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-trim\fR 0 openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-trim\fR 1000 \fB\-\-trimRange\fR 2000 openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-provision\fR 134217728 openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-setMaxLBA\fR 134217728 +openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-setMaxLBA\fR 134217728 \fB\-\-changeIdString\fR openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-restoreMaxLBA\fR +openSeaChest_Basics \fB\-d\fR /dev/sg<#> \fB\-\-capacityModelNumberMapping\fR .PP Return codes ============ @@ -279,6 +281,16 @@ is available. Use this option to issue a fast scan on the specified drive. .HP +\fB\-\-capacityModelNumberMapping\fR +.IP +Use this option to display the capacity model number mapping +TBD +.HP +\fB\-\-changeIdString\fR +.IP +Use this option to change ID string according to capacity \- model number +mapping. Need to use together with \fB\-\-setMaxLBA\fR or \fB\-\-restoreMaxLBA\fR +.HP \fB\-\-checkPowerMode\fR .IP Get the current power mode of a drive. @@ -560,15 +572,36 @@ Use one of these options to specify a range to trim or unmap on a drive. A starting point must be specified with the \fB\-\-trim\fR/\-\-unmapRange option. .IP -Utility Version: 3.5.4 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Basics \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Basics Version: 3.6.2\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Basics: +.IP +Utility Version: 3.6.2 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Basics +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Basics +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Basics +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Configure.8 b/docs/man/man8/openSeaChest_Configure.8 index 2acc58c7..4c6fb1be 100644 --- a/docs/man/man8/openSeaChest_Configure.8 +++ b/docs/man/man8/openSeaChest_Configure.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Configure:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_CONFIGURE "1" "August 2024" "openSeaChest_Configure ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Configure \- manual page for openSeaChest_Configure ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Configure \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Configure Version: 2.5.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:13 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Configure Version: 2.7.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user .PP ========================================================================================== Usage @@ -50,6 +50,8 @@ openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-scsiMPRestore\fR 3Fh\-FFh openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-setSCSIMP\fR 08:2:2:1=0 openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-setSCSIMP\fR file=modePageToChange.txt openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-provision\fR 134217728 +openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-setMaxLBA\fR 134217728 \fB\-\-changeIdString\fR +openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-capacityModelNumberMapping\fR openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-dcoIdentify\fR openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-dcoRestore\fR openSeaChest_Configure \fB\-d\fR /dev/sg<#> \fB\-\-dcoFreezeLock\fR @@ -254,6 +256,16 @@ is available. Use this option to issue a fast scan on the specified drive. .HP +\fB\-\-capacityModelNumberMapping\fR +.IP +Use this option to display the capacity model number mapping +TBD +.HP +\fB\-\-changeIdString\fR +.IP +Use this option to change ID string according to capacity \- model number +mapping. Need to use together with \fB\-\-setMaxLBA\fR or \fB\-\-restoreMaxLBA\fR +.HP \fB\-\-phySpeed\fR [0 | 1 | 2 | 3 | 4 | 5] .IP Use this option to change the PHY speed to a @@ -455,13 +467,24 @@ Note: Some products will support low, but not the ultra .IP low current spinup mode. .TP -\fB\-\-puisFeature\fR [ enable | disable ] +\fB\-\-puisFeature\fR [ info | spinup | enable | disable ] (SATA Only) .IP Use this option to enable or disable the power up in standby (PUIS) feature on SATA drives. +Arguments: +.TP +info +\- display information about the PUIS support on the device +.TP +spinup +\- issue the PUIS spinup set features command to spin up +.TP +the device to active/idle state. +enable \- enable the PUIS feature using setfeatures command +disable \- disable the PUIS feature using setfeatures command +.TP Note: If this is configured on the drive with a jumper, this -.IP command will fail. .IP Note2: Not all products support this feature. @@ -559,6 +582,40 @@ The maximum time that can be specified is 1 hour, 49 minutes, 13 seconds Using the "default" argument restores default settings. Note: On some SAT HBAs/bridges, status will not be able to be determined due to HBA/bridge limitations. +.TP +\fB\-\-wrv\fR [ info | all | vendor | # | disable ] +(SATA Only) +.IP +This option can report the current configuration of the +ATA Write\-Read\-Verify feature, enable the feature, or +disable the feature. +Enabling this feature instructs the device to perform a +verification of all data after it has been written. +Enabling this may result in lower device performance. +If write caching is enabled, this feature may return +completion before writing to the medium and verifying +the medium. If Write caching is disabled, the write and +verification must complete before returning command status. +Argument usage: +.TP +info +\- Display the current status of the feature +.TP +all +\- set verification on for all written sectors +.TP +vendor +\- set verification for the 1st vendor specific +.IP +number of sectors. +.TP +# +\- Perform verification for the first user defined +.TP +number of sectors. Note: This is rounded up to the +nearest 1024 sectors. Max value of 261120 sectors. +.IP +disable \- disable the Write\-Read\-Verify feature. .IP SAS Only: ======== @@ -744,15 +801,36 @@ the provisioning again. This command erases all data between the new maxLBA specified and the current maxLBA of the device. using a TRIM/UNMAP command. .IP -Utility Version: 2.5.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Configure \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Configure Version: 2.7.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Configure: +.IP +Utility Version: 2.7.1 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Configure +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Configure +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Configure +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Defect.8 b/docs/man/man8/openSeaChest_Defect.8 new file mode 100644 index 00000000..8ae556b0 --- /dev/null +++ b/docs/man/man8/openSeaChest_Defect.8 @@ -0,0 +1,404 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_DEFECT "1" "August 2024" "openSeaChest_Defect ==========================================================================================" "User Commands" +.SH NAME +openSeaChest_Defect \- manual page for openSeaChest_Defect ========================================================================================== +.SH DESCRIPTION +========================================================================================== +.IP +openSeaChest_Defect \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Defect Version: 0.9.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user +.PP +========================================================================================== +Usage +===== +.IP +openSeaChest_Defect [\-d <sg_device>] {arguments} {options} +.PP +Examples +======== +.IP +openSeaChest_Defect \fB\-\-scan\fR +openSeaChest_Defect \fB\-d\fR /dev/sg<#> \fB\-i\fR +.PP +Return codes +============ +.IP +Generic/Common exit codes +0 = No Error Found +1 = Error in command line options +2 = Invalid Device Handle or Missing Device Handle +3 = Operation Failure +4 = Operation not supported +5 = Operation Aborted +6 = File Path Not Found +7 = Cannot Open File +8 = File Already Exists +9 = Need Elevated Privileges +Anything else = unknown error +.PP +Utility Options +=============== +.HP +\fB\-\-echoCommandLine\fR +.IP +Echo the command line entered into the utility on the screen. +.HP +\fB\-\-enableLegacyUSBPassthrough\fR +.IP +Only use this option on old USB or IEEE1394 (Firewire) +products that do not otherwise work with the tool. +This option will enable a trial and error method that +attempts sending various ATA Identify commands through +vendor specific means. Because of this, certain products +that may respond in unintended ways since they may interpret +these commands differently than the bridge chip the command +was designed for. +.HP +\fB\-\-forceATA\fR +.IP +Using this option will force the current drive to +be treated as a ATA drive. Only ATA commands will +be used to talk to the drive. +.TP +\fB\-\-forceATADMA\fR +(SATA Only) +.IP +Using this option will force the tool to issue SAT +commands to ATA device using the protocol set to DMA +whenever possible (on DMA commands). +This option can be combined with \fB\-\-forceATA\fR +.TP +\fB\-\-forceATAPIO\fR +(SATA Only) +.IP +Using this option will force the tool to issue PIO +commands to ATA device when possible. This option can +be combined with \fB\-\-forceATA\fR +.TP +\fB\-\-forceATAUDMA\fR +(SATA Only) +.IP +Using this option will force the tool to issue SAT +commands to ATA device using the protocol set to UDMA +whenever possible (on DMA commands). +This option can be combined with \fB\-\-forceATA\fR +.HP +\fB\-\-forceSCSI\fR +.IP +Using this option will force the current drive to +be treated as a SCSI drive. Only SCSI commands will +be used to talk to the drive. +.HP +\fB\-h\fR, \fB\-\-help\fR +.IP +Show utility options and example usage (this output you see now) +Please report bugs/suggestions to seaboard@seagate.com. +Include the output of \fB\-\-version\fR information in the email. +.HP +\fB\-\-license\fR +.IP +Display the Seagate End User License Agreement (EULA). +.HP +\fB\-\-modelMatch\fR [model Number] +.IP +Use this option to run on all drives matching the provided +model number. This option will provide a closest match although +an exact match is preferred. Ex: ST500 will match ST500LM0001 +.HP +\fB\-\-noBanner\fR +.IP +Use this option to suppress the text banner that displays each time +openSeaChest is run. +.HP +\fB\-\-onlyFW\fR [firmware revision] +.IP +Use this option to run on all drives matching the provided +firmware revision. This option will only do an exact match. +.HP +\fB\-\-onlySeagate\fR +.IP +Use this option to match only Seagate drives for the options +provided +.HP +\fB\-q\fR, \fB\-\-quiet\fR +.IP +Run openSeaChest_Defect in quiet mode. This is the same as +\fB\-v\fR 0 or \fB\-\-verbose\fR 0 +.HP +\fB\-v\fR [0\-4], \fB\-\-verbose\fR [0 | 1 | 2 | 3 | 4] +.IP +Show verbose information. Verbosity levels are: +0 \- quiet +1 \- default +2 \- command descriptions +3 \- command descriptions and values +4 \- command descriptions, values, and data buffers +Example: \fB\-v\fR 3 or \fB\-\-verbose\fR 3 +.HP +\fB\-V\fR, \fB\-\-version\fR +.IP +Show openSeaChest_Defect version and copyright information & exit +.PP +Utility Arguments +================= +.HP +\fB\-d\fR, \fB\-\-device\fR [deviceHandle | all] +.IP +Use this option with most commands to specify the device +handle on which to perform an operation. Example: /dev/sg<#> +To run across all devices detected in the system, use the +"all" argument instead of a device handle. +Example: \fB\-d\fR all +NOTE: The "all" argument is handled by running the +.TP +specified options on each drive detected in the +OS sequentially. For parallel operations, please +use a script opening a separate instance for each +device handle. +.HP +\fB\-F\fR, \fB\-\-scanFlags\fR [option list] +.IP +Use this option to control the output from scan with the +options listed below. Multiple options can be combined. +.TP +ata \- show only ATA (SATA) devices +usb \- show only USB devices +scsi \- show only SCSI (SAS) devices +nvme \- show only NVMe devices +interfaceATA \- show devices on an ATA interface +interfaceUSB \- show devices on a USB interface +interfaceSCSI \- show devices on a SCSI or SAS interface +interfaceNVME = show devices on an NVMe interface +sd \- show sd device handles +sgtosd \- show the sd and sg device handle mapping +.HP +\fB\-i\fR, \fB\-\-deviceInfo\fR +.IP +Show information and features for the storage device +.HP +\fB\-s\fR, \fB\-\-scan\fR +.IP +Scan the system and list all storage devices with logical +/dev/sg<#> assignments. Shows model, serial and firmware +numbers. If your device is not listed on a scan immediately +after booting, then wait 10 seconds and run it again. +.HP +\fB\-S\fR, \fB\-\-Scan\fR +.IP +This option is the same as \fB\-\-scan\fR or \fB\-s\fR, +however it will also perform a low level rescan to pick up +other devices. This low level rescan may wake devices from low +power states and may cause the OS to re\-enumerate them. +Use this option when a device is plugged in and not discovered in +a normal scan. +NOTE: A low\-level rescan may not be available on all interfaces or +all OSs. The low\-level rescan is not guaranteed to find additional +devices in the system when the device is unable to come to a ready state. +.HP +\fB\-\-SATInfo\fR +.IP +Displays SATA device information on any interface +using both SCSI Inquiry / VPD / Log reported data +(translated according to SAT) and the ATA Identify / Log +reported data. +.HP +\fB\-\-testUnitReady\fR +.IP +Issues a SCSI Test Unit Ready command and displays the +status. If the drive is not ready, the sense key, asc, +ascq, and fru will be displayed and a human readable +translation from the SPC spec will be displayed if one +is available. +.HP +\fB\-\-fastDiscovery\fR +.TP +Use this option +to issue a fast scan on the specified drive. +.HP +\fB\-\-errorLimit\fR [limit in number of LBAs] +.IP +Use this option to specify a different error +limit for a user generic or long generic read +test or DST and Clean. This must be a number of +.IP +logical LBAs to have errors. If a drive has multiple +logical sectors per physical sector, this number will +.IP +be adjusted for you to reflect the drive +architecture. +.HP +\fB\-\-checkGrownListCount\fR [count to check] +.IP +Use this option to check if the grown defect list count is +greater than the provided value. +.HP +\fB\-\-checkPendingListCount\fR [count to check] +.IP +Use this option to check if the pending defect list count is +greater than the provided value. +NOTE: This only works on SAS products that support the Pending +Defects log page from SBC4 or later +.HP +\fB\-\-showPendingList\fR (Seagate Only) +.IP +Use this option to show the pending defect list +as it is reported by the drive. +NOTE: SBC4 pending log required for SAS support. +.IP +SAS Only: +.HP +\fB\-\-defectFormat\fR [ # | shortBlock | longBlock | xbfi | xchs | bfi | chs ] (SAS Only) +.IP +This option set the format of the defects to output. +Not all drives will support all defect modes! +SSDs will only support block modes! +Arguments: (name | #) +.IP +shortBlock | 0 \- show the defects in short block address mode (drives < 32bit LBA) +xbfi | 1 \- show the defects in extended bytes from index mode +xchs | 2 \- show the defects in extended physical cylinder\-head\-sector mode +longBlock | 3 \- show the defects in long block address mode (drives > 32bit LBA) +bfi | 4 \- show the defects in bytes from index mode +chs | 5 \- show the defects in physical cylinder\-head\-sector mode +.TP +\fB\-\-showSCSIDefects\fR [ p | g | pg ] +(SAS Only) +.IP +This option will display the SCSI defects on the screen. +The arguments to this will tell whether to get the grown, +primary, or primary and grown defects from the drive. +Use the \fB\-\-defectFormat\fR option to specify the mode to display the defects. +If no mode is specified, physical cylinder\-head\-sector mode is assumed +Arguments: +.IP +p \- use this option to pull and display the primary (factory) defects +g \- use this option to pull and display the grown (reallocated) defects +.IP +The above options can be combined to pull and display both defect lists. +.PP +Data Destructive Commands (Seagate only) +======================================== +.TP +\fB\-\-bytesToCorrupt\fR [# of bytes] +(Seagate Only) +.IP +Use this option to specify the number of data bytes to change +when used with the \fB\-\-corruptLBA\fR option. +.HP +\fB\-\-dstAndClean\fR +.IP +Runs DST, then checks for an error and repairs the +error if possible. This continues until all errors +reported by DST are fixed, or when the error limit is +reached. The default limit is 50 errors. +.TP +\fB\-\-corruptLBA\fR [lba] +(Seagate Only) +.IP +Use this option to corrupt the data bytes of an LBA. The +\fB\-\-bytesToCorrupt\fR option can be used to specify the number of bytes to +corrupt. If that option is not given, a default will be used +that attempts to create a correctable error on the drive. +This option can be used to create uncorrectable or correctable +errors on a drive, depending on it's ECC algorithm and the number +of corrupted data bytes. +.TP +\fB\-\-corruptRandomLBAs\fR [# of LBAs to corrupt] +(Seagate Only) +.IP +This option will corrupt the specified number of LBAs randomly +on the device. The \fB\-\-bytesToCorrupt\fR option can be used to specify the number of bytes to +corrupt. If that option is not given, a default will be used +that attempts to create a correctable error on the drive. +This option can be used to create uncorrectable or correctable +errors on a drive, depending on it's ECC algorithm and the number +of corrupted data bytes. +.TP +\fB\-\-corruptRange\fR [# of LBAs] +(Seagate Only) +.IP +This option is used with the \fB\-\-corruptLBA\fR option to +corrupt a range of LBAs on the drive. +.HP +\fB\-\-disableReadUncorrectables\fR +.IP +Use this option to disable issuing read commands to the LBAs +where errors are written. This option should only be used for +debugging. When this option is used, the uncorrectable errors +may not end up being logged in the Pending Defect List on the +drive. +.TP +\fB\-\-flaggedUncorrectable\fR +(Seagate Only) +.IP +Use this option to flag an uncorrectable error instead of +creating a pseudo uncorrectable error with the +\fB\-\-psuedoUncorrectable\fR or \fB\-\-randomUncorrectables\fR options. +Error types: +.TP +Pseudo \- creates a pseudo uncorrectable error. The device +will perform full error recovery and logging on failure. +.TP +Flagged \- flags an error. The device will not perform error +recovery and will not log on failure. +.TP +\fB\-\-psuedoUncorrectable\fR [lba] +(Seagate Only) +.IP +Use this option to create a uncorrectable error at +the specified LBA. Use \fB\-\-uncorrectableRange\fR to specify a range. +By default, pseudo uncorrectable errors will be created for +the entire physical sector. Use the \fB\-\-flaggedUncorrectable\fR option +to flag errors instead. Flagged errors do not get logged +or have any error processing when encountered. +.TP +\fB\-\-randomUncorrectables\fR [number of errors] +(Seagate Only) +.IP +Use this option to create a number of random uncorrectable +LBAs on a drive. +.TP +\fB\-\-uncorrectableRange\fR [range] +(Seagate Only) +.IP +Use this option to specify a range of LBAs to create an +uncorrectable error at. This option must be used with the +\fB\-\-psuedoUncorrectable\fR or \fB\-\-flaggedUncorrectable\fR options so that a +starting LBA is specified. +.IP +openSeaChest_Defect \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Defect Version: 0.9.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Defect: +.IP +Utility Version: 0.9.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 +Compiled Architecture: X86_64 +Detected Endianness: Little Endian +Compiler Used: GCC +Compiler Version: 11.4.0 +Operating System Type: Linux +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Defect +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Defect +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Defect +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Erase.8 b/docs/man/man8/openSeaChest_Erase.8 index fc1f7dee..1d90c06e 100644 --- a/docs/man/man8/openSeaChest_Erase.8 +++ b/docs/man/man8/openSeaChest_Erase.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Erase:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_ERASE "1" "August 2024" "openSeaChest_Erase ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Erase \- manual page for openSeaChest_Erase ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Erase \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Erase Version: 4.3.6\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:13 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Erase Version: 4.6.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user .PP ========================================================================================== Usage @@ -315,6 +315,16 @@ Configuration Overlay) features in accordance with the specifications. If the restore completes without error, then the erase will proceed and additional errors will only be in relation to those erasure methods. .HP +\fB\-\-refreshfs\fR +.IP +This option will call an OS unique low\-level routine to rescan +a device for any file systems it can detect through the +partition table. The detected filesystems will vary by OS +and OS capabilities. +This option is useful to call after completing a full disk erase +as it may make a cached volume in the OS go away or detect that a device +is empty and ready to have a new file system written to it. +.HP \fB\-\-showEraseSupport\fR .IP This option checks the drive to determine which methods of @@ -418,6 +428,26 @@ written according to the expectation that the device firmware will meet these capabilities as defined in the appropriate standards from T10, T13, SATA \- IO, and NVMexpress. ========================= +.HP +\fB\-\-ause\fR +.IP +Use this option to allow running a sanitize operation in +unrestricted mode. Without this option, all sanitize options +are run in restricted mode by default. +In unrestricted mode, if a sanitize erase fails the drive enters +a failure state. The failure state can be cleared with a Sanitize +exit failure mode command, or it can be cleared with a successful +sanitize erase. +In restricted mode, if a sanitize fails, the failure state can only +be cleared with a successful sanitize erase. +.HP +\fB\-\-ipbp\fR +.IP +Use this option to instruct the drive to invert the requested +sanitize overwrite pattern between each overwrite pass. +For the default pattern of all zeroes, this means that after +a first pass of zeroes, the second pass will be all 1's (binary) +or all F's (hexadecimal) .TP \fB\-\-overwrite\fR [starting LBA] (Clear) @@ -433,6 +463,18 @@ seconds) to erase a portion of the drive. Use with the overwrite option (\fB\-\-overwrite\fR) to erase a range of LBAs on the selected drive. .HP +\fB\-\-overwritepasses\fR [ number of overwrite passes ] +.IP +Specify the number of overwrite passes to use during a sanitize +overwrite operation. By default, only a single overwrite pass +is used unless this option specifies a different value. +The maximum number of passes varies by drive type: +ATA: 16 passes +NVMe: 16 passes +SCSI: 31 passes +Use the \fB\-\-ipbp\fR option to instruct the device to invert +the pattern between each overwrite pass. +.HP \fB\-\-pattern\fR [repeat:asciinospaces | random | increment:startValue | file:filename] .IP Use this option with overwrite, sanitize, and format unit @@ -489,6 +531,24 @@ sanitize erase operations are persistent across a power cycle and cannot be stopped Example: \fB\-\-sanitize\fR blockerase \fB\-\-poll\fR .IP +By default, sanitize runs in restricted exit mode, meaning the +only way to exit a failed sanitize is to attempt sanitize again +until it completes successfully. Add the \fB\-\-ause\fR option to run +in unrestricted mode. In unrestricted mode, if sanitize fails +you can exit this mode with the "exit failure mode" command +or a successful sanitize command. +.IP +For Zoned block devices, the \fB\-\-znr\fR option can be used +to stop the write pointers from resetting allowing full +drive verification to be performed upon completion of sanitize +For NVMe devices that support the deallocate feature (TRIM), the +\fB\-\-nodeallocate\fR option can be used to prevent the deallocation of blocks at +completion of sanitize to allow for full drive verification. +NOTE: An NVMe controller may inhibit the no deallocate behavior +.TP +and may deallocate anyways or fail the sanitize command when +no deallocate is specified. +.IP * blockerase on some solid state drives is very fast at less than one (1) second, while others may take more that 30 seconds This operation performs a physical low level block erase @@ -500,21 +560,16 @@ changes the internal encryption keys that are used for user data causing all previous data to be useless. .IP * overwrite is a physical overwrite on all current, past, and -potential user data. The ATA and SCSI specifications allow a +potential user data. The ATA, NVMe, & SCSI specifications allow a user defined pattern and multiple passes. openSeaChest_Erase will -use a zero pattern and a single pass for this operation. +use a zero pattern and a single pass for this operation +by default. Use \fB\-\-overwritepasses\fR and \fB\-\-ipbp\fR to specify +the number of passes and whether to invert the pattern between +each overwrite pass. .IP -* freezelock is a command to block processing of sanitize -operations until a power cycle is performed on a device. -It is only available on ATA drives. Once this command has been -sent, the freezelock status becomes immediate and cannot be -cleared until the drive has been powered off. All sanitize -commands, except a sanitize status will be aborted. +* freezelock \- migrate to use of \fB\-\-sanitizeFreeze\fR .IP -* antifreezelock is a command that is designed to block a -freezelock command from locking out the sanitize feature set. -It is only available on ATA drives that support the ACS3, or -newer specification. +* antifreezelock \- migrate to use of \fB\-\-sanitizeAntiFreeze\fR .TP WARNING: Sanitize may affect all LUNs/namespaces for devices with multiple logical units or namespaces. @@ -560,6 +615,14 @@ sanitize overwrite to accomplish this. .IP Specify a range to writesame to. Use this option with the writeSame option in order to begin a write same operation. +.HP +\fB\-\-znr\fR +.IP +For ZBD's (Zoned Block Devices), use this option during a +Sanitize or ATA Security Erase to specify leaving all zones +full so that full verification of erasure can be performed. +When this option is not specified, all zones will be empty +upon completion of these erases. .IP SATA Only: ========= @@ -590,6 +653,24 @@ data areas. user data with a vendor specific pattern. Some Seagate Instant Secure Erase will perform a cryptographic erase instead of an overwrite. +.TP +\fB\-\-sanitizeAntiFreeze\fR +(SATA Only) +.IP +Antifreezelock is a command that is designed to block a +freezelock command from locking out the sanitize feature set. +It is only available on ATA drives that support the ACS3, or +newer specification. +.TP +\fB\-\-sanitizeFreeze\fR +(SATA Only) +.IP +Freezelock is a command to block processing of sanitize +operations until a power cycle is performed on a device. +It is only available on ATA drives. Once this command has been +sent, the freezelock status becomes immediate and cannot be +cleared until the drive has been powered off. All sanitize +commands, except a sanitize status will be aborted. .IP SAS Only: ========= @@ -667,6 +748,20 @@ fast format to common sizes like 4K or 512B due to these customer requirements. .IP NVMe Only: ========= +\fB\-\-nodeallocate\fR (NVMe Only) +.IP +For NVMe devices, specify this option during a sanitize to +leave all blocks allocated after a sanitize erase. By default +an NVMe controller will deallocate (TRIM/Unmap) all the LBAs. +Using this option allows for full verification of erasure after +a Sanitize command. +NOTE: An NVMe controller may inhibit this option in certain +configurations meaning the sanitize may produce a warning or +a failure depending on how this is configured on the controller. +After verifying an erasure with this option, run a deallocate/TRIM +across the entire device/namespace to match default behavior of +a sanitize erase. +.HP \fB\-\-nvmFmtMetadataSet\fR [ xlba | separate ] (NVMe Only) .IP Use this option to specify how metadata is transmitted to @@ -753,15 +848,36 @@ option to be provided. Without this option the controller may not erase all user data and substitute returning zeroes for performance instead. .IP -Utility Version: 4.3.6 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Erase \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Erase Version: 4.6.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143604 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Erase: +.IP +Utility Version: 4.6.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Erase +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Erase +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Erase +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Firmware.8 b/docs/man/man8/openSeaChest_Firmware.8 index ee02a162..854d07de 100644 --- a/docs/man/man8/openSeaChest_Firmware.8 +++ b/docs/man/man8/openSeaChest_Firmware.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Firmware:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_FIRMWARE "1" "August 2024" "openSeaChest_Firmware ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Firmware \- manual page for openSeaChest_Firmware ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Firmware \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Firmware Version: 4.0.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:13 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Firmware Version: 4.2.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user .PP ========================================================================================== Usage @@ -352,15 +352,36 @@ valid firmware image in it as well. WARNING: Switching firmware may affect all LUNs/namespaces for devices with multiple logical units or namespaces. .IP -Utility Version: 4.0.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Firmware \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Firmware Version: 4.2.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Firmware: +.IP +Utility Version: 4.2.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Firmware +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Firmware +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Firmware +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Format.8 b/docs/man/man8/openSeaChest_Format.8 index c957bb4f..ede47a38 100644 --- a/docs/man/man8/openSeaChest_Format.8 +++ b/docs/man/man8/openSeaChest_Format.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Format:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_FORMAT "1" "August 2024" "openSeaChest_Format ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Format \- manual page for openSeaChest_Format ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Format \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Format Version: 3.0.4\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:13 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Format Version: 3.2.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user .PP ========================================================================================== Usage @@ -657,15 +657,36 @@ option to be provided. Without this option the controller may not erase all user data and substitute returning zeroes for performance instead. .IP -Utility Version: 3.0.4 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Format \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Format Version: 3.2.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Format: +.IP +Utility Version: 3.2.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Format +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Format +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Format +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_GenericTests.8 b/docs/man/man8/openSeaChest_GenericTests.8 index 7a62c9cc..ef5e5119 100644 --- a/docs/man/man8/openSeaChest_GenericTests.8 +++ b/docs/man/man8/openSeaChest_GenericTests.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_GenericTests:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_GENERICTESTS "1" "August 2024" "openSeaChest_GenericTests ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_GenericTests \- manual page for openSeaChest_GenericTests ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_GenericTests \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_GenericTests Version: 2.2.2\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_GenericTests Version: 2.3.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user .PP ========================================================================================== Usage @@ -427,15 +427,36 @@ Use this option to repair any bad sectors found during a long or user generic read test as they are found. .IP -Utility Version: 2.2.2 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_GenericTests \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_GenericTests Version: 2.3.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_GenericTests: +.IP +Utility Version: 2.3.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_GenericTests +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_GenericTests +programs are properly installed at your site, the command +.IP +.B info openSeaChest_GenericTests +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Info.8 b/docs/man/man8/openSeaChest_Info.8 index 93b45c22..48a93e51 100644 --- a/docs/man/man8/openSeaChest_Info.8 +++ b/docs/man/man8/openSeaChest_Info.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Info:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_INFO "1" "August 2024" "openSeaChest_Info ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Info \- manual page for openSeaChest_Info ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Info \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Info Version: 2.5.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Info Version: 2.7.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user .PP ========================================================================================== Usage @@ -250,7 +250,13 @@ Currently only MBR and GPT partition tables are supported. .IP SATA Only: ========= -\fB\-\-smartAttributes\fR [raw | hybrid | analyzed] (SATA Only) +\fB\-\-showPhyEvents\fR (SATA Only) +.IP +Use this option to display a SATA device's supported +event counters. +.TP +\fB\-\-smartAttributes\fR [raw | hybrid | analyzed] +(SATA Only) .IP The drive will display its list of supported SMART attributes. Some attributes names are commonly standard and most others are @@ -305,15 +311,36 @@ g \- use this option to pull and display the grown (reallocated) defects .IP The above options can be combined to pull and display both defect lists. .IP -Utility Version: 2.5.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Info \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Info Version: 2.7.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Info: +.IP +Utility Version: 2.7.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Info +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Info +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Info +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Logs.8 b/docs/man/man8/openSeaChest_Logs.8 index ae164f3c..3b9ef1bb 100644 --- a/docs/man/man8/openSeaChest_Logs.8 +++ b/docs/man/man8/openSeaChest_Logs.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Logs:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_LOGS "1" "August 2024" "openSeaChest_Logs ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Logs \- manual page for openSeaChest_Logs ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Logs \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Logs Version: 2.4.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Logs Version: 2.5.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user .PP ========================================================================================== Usage @@ -391,15 +391,36 @@ WARNING: Vendor Unique Logs pulled using this option may not be valid due to unknown vendor unique bits in ATA/SCSI/NVMe etc. command fields. .IP -Utility Version: 2.4.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Logs \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Logs Version: 2.5.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Logs: +.IP +Utility Version: 2.5.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Logs +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Logs +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Logs +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_NVMe.8 b/docs/man/man8/openSeaChest_NVMe.8 index f99a26ad..7b43e31b 100644 --- a/docs/man/man8/openSeaChest_NVMe.8 +++ b/docs/man/man8/openSeaChest_NVMe.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_NVMe:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_NVME "1" "August 2024" "openSeaChest_NVMe ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_NVMe \- manual page for openSeaChest_NVMe ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_NVMe \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_NVMe Version: 2.3.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_NVMe Version: 2.4.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user .PP ========================================================================================== Usage @@ -43,6 +43,7 @@ openSeaChest_NVMe \fB\-d\fR /dev/sg<#> \fB\-\-nvmFormat\fR current \fB\-\-poll\f Checking and changing power states: openSeaChest_NVMe \fB\-d\fR /dev/sg<#> \fB\-\-checkPowerMode\fR openSeaChest_NVMe \fB\-d\fR /dev/sg<#> \fB\-\-transitionPowerState\fR 1 +openSeaChest_NVMe \fB\-d\fR /dev/sg<#> \fB\-\-showNVMPowerStates\fR Pulling the Telemetry log: openSeaChest_NVMe \fB\-d\fR /dev/sg<#> \fB\-\-getTelemetry\fR host openSeaChest_NVMe \fB\-d\fR /dev/sg<#> \fB\-\-getTelemetry\fR host, \fB\-\-telemetryDataArea\fR 2 \fB\-\-logMode\fR bin @@ -358,6 +359,10 @@ Supported Data Area. 2 \- get telemetry data additional to data area 2 3 \- get telemetry data additional to data area 3 (default data area) .HP +\fB\-\-listSupportedLogs\fR +.IP +Displays a list of all supported logs by this device type. +.HP \fB\-\-onlyFW\fR [firmware revision] .IP Use this option to run on all drives matching the provided @@ -413,6 +418,11 @@ Use this option to get the NVMe Temperature Statistics \fB\-\-pciStats\fR .IP Use this option to get the NVMe PCIe Statistics +.TP +\fB\-\-showNVMPowerStates\fR +(NVMe Only) +.IP +Use this option to display a device's supported power states. .HP \fB\-\-showSupportedFormats\fR .IP @@ -517,15 +527,36 @@ option to be provided. Without this option the controller may not erase all user data and substitute returning zeroes for performance instead. .IP -Utility Version: 2.3.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_NVMe \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_NVMe Version: 2.4.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143605 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_NVMe: +.IP +Utility Version: 2.4.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_NVMe +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_NVMe +programs are properly installed at your site, the command +.IP +.B info openSeaChest_NVMe +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_PassthroughTest.8 b/docs/man/man8/openSeaChest_PassthroughTest.8 index a81132b2..0a6bdba2 100644 --- a/docs/man/man8/openSeaChest_PassthroughTest.8 +++ b/docs/man/man8/openSeaChest_PassthroughTest.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_PassthroughTest:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_PASSTHROUGHTEST "1" "August 2024" "openSeaChest_PassthroughTest ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_PassthroughTest \- manual page for openSeaChest_PassthroughTest ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_PassthroughTest \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_PassthroughTest Version: 1.3.3\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_PassthroughTest Version: 1.4.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user .PP ========================================================================================== Usage @@ -302,15 +302,36 @@ behavior. The other options to control the test are as follows: \fB\-\-enableHangCmdsTest\fR \fB\-\-forceRetest\fR .IP -Utility Version: 1.3.3 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_PassthroughTest \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_PassthroughTest Version: 1.4.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_PassthroughTest: +.IP +Utility Version: 1.4.1 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_PassthroughTest +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_PassthroughTest +programs are properly installed at your site, the command +.IP +.B info openSeaChest_PassthroughTest +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_PowerControl.8 b/docs/man/man8/openSeaChest_PowerControl.8 index 9b8088fa..4ae10265 100644 --- a/docs/man/man8/openSeaChest_PowerControl.8 +++ b/docs/man/man8/openSeaChest_PowerControl.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_PowerControl:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_POWERCONTROL "1" "August 2024" "openSeaChest_PowerControl ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_PowerControl \- manual page for openSeaChest_PowerControl ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_PowerControl \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_PowerControl Version: 3.4.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_PowerControl Version: 3.6.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user .PP ========================================================================================== Usage @@ -499,6 +499,35 @@ NOTE: Please ensure that the host adapter/controller/driver can handle this before enabling it, otherwise the drive link may go down and the device will not be able to communicate. .TP +\fB\-\-puisFeature\fR [ info | spinup | enable | disable ] +(SATA Only) +.IP +Use this option to enable or disable the power up in standby +(PUIS) feature on SATA drives. +Arguments: +.TP +info +\- display information about the PUIS support on the device +.TP +spinup +\- issue the PUIS spinup set features command to spin up +.TP +the device to active/idle state. +enable \- enable the PUIS feature using setfeatures command +disable \- disable the PUIS feature using setfeatures command +.TP +Note: If this is configured on the drive with a jumper, this +command will fail. +.IP +Note2: Not all products support this feature. +WARNING: Before enabling this feature on any SAS/SATA HBA, +.TP +check the HBA documentation to see if this feature +is supported by the HBA. Enabling this on an HBA that +does not support this feature will cause the drive to +stop showing up to the host OS or even in the HBA's +firmware/BIOS/UEFI configuration. +.TP \fB\-\-setAPMLevel\fR [1 \- 254] (SATA Only) .IP @@ -627,15 +656,36 @@ HINT: .IP Use \fB\-\-showNVMPowerStates\fR to view the supported states .IP -Utility Version: 3.4.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_PowerControl \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_PowerControl Version: 3.6.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_PowerControl: +.IP +Utility Version: 3.6.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_PowerControl +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_PowerControl +programs are properly installed at your site, the command +.IP +.B info openSeaChest_PowerControl +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Raw.8 b/docs/man/man8/openSeaChest_Raw.8 new file mode 100644 index 00000000..ef8a33b4 --- /dev/null +++ b/docs/man/man8/openSeaChest_Raw.8 @@ -0,0 +1,600 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_RAW "1" "August 2024" "openSeaChest_Raw ==========================================================================================" "User Commands" +.SH NAME +openSeaChest_Raw \- manual page for openSeaChest_Raw ========================================================================================== +.SH DESCRIPTION +========================================================================================== +.IP +openSeaChest_Raw \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Raw Version: 0.9.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Usage +===== +.IP +openSeaChest_Raw [\-d <sg_device>] {arguments} {options} +.PP +Examples +======== +.IP +openSeaChest_Raw \fB\-\-scan\fR +openSeaChest_Raw \fB\-d\fR /dev/sg<#> \fB\-i\fR +Identify device: +.TP +\fB\-d\fR /dev/sg<#> \fB\-\-dataDir\fR in +\fB\-\-dataLen\fR 512 \fB\-\-outputFile\fR ID_dev.bin \fB\-\-tfrByteBlock\fR 512 \fB\-\-tfrProtocol\fR pio \fB\-\-tfrSize\fR 28 \fB\-\-command\fR ECh \fB\-\-tfrXferLengthReg\fR sectorCount \fB\-\-sectorCount\fR 1 +.PP +Return codes +============ +.IP +Generic/Common exit codes +0 = No Error Found +1 = Error in command line options +2 = Invalid Device Handle or Missing Device Handle +3 = Operation Failure +4 = Operation not supported +5 = Operation Aborted +6 = File Path Not Found +7 = Cannot Open File +8 = File Already Exists +9 = Need Elevated Privileges +Anything else = unknown error +.PP +Utility Options +=============== +.HP +\fB\-\-echoCommandLine\fR +.IP +Echo the command line entered into the utility on the screen. +.HP +\fB\-\-enableLegacyUSBPassthrough\fR +.IP +Only use this option on old USB or IEEE1394 (Firewire) +products that do not otherwise work with the tool. +This option will enable a trial and error method that +attempts sending various ATA Identify commands through +vendor specific means. Because of this, certain products +that may respond in unintended ways since they may interpret +these commands differently than the bridge chip the command +was designed for. +.HP +\fB\-\-forceATA\fR +.IP +Using this option will force the current drive to +be treated as a ATA drive. Only ATA commands will +be used to talk to the drive. +.TP +\fB\-\-forceATADMA\fR +(SATA Only) +.IP +Using this option will force the tool to issue SAT +commands to ATA device using the protocol set to DMA +whenever possible (on DMA commands). +This option can be combined with \fB\-\-forceATA\fR +.TP +\fB\-\-forceATAPIO\fR +(SATA Only) +.IP +Using this option will force the tool to issue PIO +commands to ATA device when possible. This option can +be combined with \fB\-\-forceATA\fR +.TP +\fB\-\-forceATAUDMA\fR +(SATA Only) +.IP +Using this option will force the tool to issue SAT +commands to ATA device using the protocol set to UDMA +whenever possible (on DMA commands). +This option can be combined with \fB\-\-forceATA\fR +.HP +\fB\-\-forceSCSI\fR +.IP +Using this option will force the current drive to +be treated as a SCSI drive. Only SCSI commands will +be used to talk to the drive. +.HP +\fB\-h\fR, \fB\-\-help\fR +.IP +Show utility options and example usage (this output you see now) +Please report bugs/suggestions to seaboard@seagate.com. +Include the output of \fB\-\-version\fR information in the email. +.HP +\fB\-\-license\fR +.IP +Display the Seagate End User License Agreement (EULA). +.HP +\fB\-\-modelMatch\fR [model Number] +.IP +Use this option to run on all drives matching the provided +model number. This option will provide a closest match although +an exact match is preferred. Ex: ST500 will match ST500LM0001 +.HP +\fB\-\-noBanner\fR +.IP +Use this option to suppress the text banner that displays each time +openSeaChest is run. +.HP +\fB\-\-onlyFW\fR [firmware revision] +.IP +Use this option to run on all drives matching the provided +firmware revision. This option will only do an exact match. +.HP +\fB\-\-onlySeagate\fR +.IP +Use this option to match only Seagate drives for the options +provided +.HP +\fB\-q\fR, \fB\-\-quiet\fR +.IP +Run openSeaChest_Raw in quiet mode. This is the same as +\fB\-v\fR 0 or \fB\-\-verbose\fR 0 +.HP +\fB\-v\fR [0\-4], \fB\-\-verbose\fR [0 | 1 | 2 | 3 | 4] +.IP +Show verbose information. Verbosity levels are: +0 \- quiet +1 \- default +2 \- command descriptions +3 \- command descriptions and values +4 \- command descriptions, values, and data buffers +Example: \fB\-v\fR 3 or \fB\-\-verbose\fR 3 +.HP +\fB\-V\fR, \fB\-\-version\fR +.IP +Show openSeaChest_Raw version and copyright information & exit +.PP +Utility Arguments +================= +.HP +\fB\-d\fR, \fB\-\-device\fR [deviceHandle | all] +.IP +Use this option with most commands to specify the device +handle on which to perform an operation. Example: /dev/sg<#> +To run across all devices detected in the system, use the +"all" argument instead of a device handle. +Example: \fB\-d\fR all +NOTE: The "all" argument is handled by running the +.TP +specified options on each drive detected in the +OS sequentially. For parallel operations, please +use a script opening a separate instance for each +device handle. +.HP +\fB\-F\fR, \fB\-\-scanFlags\fR [option list] +.IP +Use this option to control the output from scan with the +options listed below. Multiple options can be combined. +.TP +ata \- show only ATA (SATA) devices +usb \- show only USB devices +scsi \- show only SCSI (SAS) devices +nvme \- show only NVMe devices +interfaceATA \- show devices on an ATA interface +interfaceUSB \- show devices on a USB interface +interfaceSCSI \- show devices on a SCSI or SAS interface +interfaceNVME = show devices on an NVMe interface +sd \- show sd device handles +sgtosd \- show the sd and sg device handle mapping +.HP +\fB\-i\fR, \fB\-\-deviceInfo\fR +.IP +Show information and features for the storage device +.HP +\fB\-s\fR, \fB\-\-scan\fR +.IP +Scan the system and list all storage devices with logical +/dev/sg<#> assignments. Shows model, serial and firmware +numbers. If your device is not listed on a scan immediately +after booting, then wait 10 seconds and run it again. +.HP +\fB\-S\fR, \fB\-\-Scan\fR +.IP +This option is the same as \fB\-\-scan\fR or \fB\-s\fR, +however it will also perform a low level rescan to pick up +other devices. This low level rescan may wake devices from low +power states and may cause the OS to re\-enumerate them. +Use this option when a device is plugged in and not discovered in +a normal scan. +NOTE: A low\-level rescan may not be available on all interfaces or +all OSs. The low\-level rescan is not guaranteed to find additional +devices in the system when the device is unable to come to a ready state. +.HP +\fB\-\-SATInfo\fR +.IP +Displays SATA device information on any interface +using both SCSI Inquiry / VPD / Log reported data +(translated according to SAT) and the ATA Identify / Log +reported data. +.HP +\fB\-\-testUnitReady\fR +.IP +Issues a SCSI Test Unit Ready command and displays the +status. If the drive is not ready, the sense key, asc, +ascq, and fru will be displayed and a human readable +translation from the SPC spec will be displayed if one +is available. +.HP +\fB\-\-fastDiscovery\fR +.TP +Use this option +to issue a fast scan on the specified drive. +.HP +\fB\-\-dataDir\fR [in | out | none] +.IP +Use this option to specify the data direction +of the entered raw command. +in \- transfer data from the device to host +out \- transfer data from the host to device +none \- no data is transferred +.HP +\fB\-\-dataLen\fR [length in bytes] +.IP +Use this option to specify the data transfer +length for a data\-in or data\-out transfer. +The following post fixes are allowed for +specifying a transfer length: +.TP +BLOCKS \- used to specify a transfer length +in device logical blocks. (Preferred) +.TP +KB \- length in kilobytes (val * 1000) +KiB \- length in kibibytes (val * 1024) +MB \- length in megabytes (val * 1000000) +MiB \- length in mebibytes (val * 1048576) +.IP +You must enter a size that is greater than or +equal to any length in the entered raw command +data. If a lesser value is entered, then the +utility may experience errors or crash. +.HP +\fB\-\-inputFile\fR [path/filename] +.IP +Use this option to specify an input file to +send to a device. Must be a binary file. +.HP +\fB\-\-inputOffset\fR [offset in bytes] +.IP +Use this option to specify the offset within +the raw input file to start sending data from. +The following post fixes are allowed for +specifying a transfer length: +.TP +BLOCKS \- used to specify an offset length +in device logical blocks. (Preferred) +.TP +KB \- length in kilobytes (val * 1000) +KiB \- length in kibibytes (val * 1024) +MB \- length in megabytes (val * 1000000) +MiB \- length in mebibytes (val * 1048576) +.HP +\fB\-\-outputFile\fR [path/filename] +.IP +Use this option to specify an output file to +save data returned from a command, or in the +case of an error, the returned error buffer. +This option will always append data to already +created files. If an error occurs on a datain +raw command, the returned error data will not be +saved to a file to prevent adding unexpected data +to the created file. +.HP +\fB\-\-timeout\fR [time in seconds] +.IP +Use this option to specify an timeout in seconds +for a raw command being sent to a device. +.IP +SATA Only: +========= +\fB\-\-aux1\fR [hex or decimal] (SATA Only) +.IP +Use this option to specify the Aux (7:0) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +NOTE: Not all interfaces support setting this register. 32B SAT CDB required. +.HP +\fB\-\-aux2\fR [hex or decimal] (SATA Only) +.IP +Use this option to specify the Aux (15:8) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +NOTE: Not all interfaces support setting this register. 32B SAT CDB required. +.HP +\fB\-\-aux3\fR [hex or decimal] (SATA Only) +.IP +Use this option to specify the Aux (23:16) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +NOTE: Not all interfaces support setting this register. 32B SAT CDB required. +.HP +\fB\-\-aux4\fR [hex or decimal] (SATA Only) +.IP +Use this option to specify the Aux (31:24) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +NOTE: Not all interfaces support setting this register. 32B SAT CDB required. +.TP +\fB\-\-auxFull\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the Aux (31:0) registers for +sending a raw SATA command. This will be interpretted as a 32bit value. +The value should be specified in hex as ??h or 0x?? or as a decimale value +NOTE: Not all interfaces support setting these registers. 32B SAT CDB required. +.TP +\fB\-\-command\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the command operation code for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-deviceHead\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the Device/Head register for +sending a raw SATA command. If this option is not provided, a value of +A0h will be used for backwards compatibility with older ATA command specifications. +NOTE: This option should be specified BEFORE the \fB\-\-lbaMode\fR option +NOTE: On 28bit read/write commands, the high 4 bits of the LBA register need to be +.IP +placed in the lower 4 bits of this register. +.IP +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-feature\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the feature register for +sending a raw SATA command. (Lower 8 bits on 48 bit commands) +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-featureExt\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the feature ext register for +sending a raw SATA command. (Upper 8 bits on 48 bit commands) +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-featFull\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the feature and feature ext register for +sending a raw SATA command. This will be interpretted as a 16bit value. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-icc\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the ICC register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +NOTE: Not all interfaces support setting this register. 32B SAT CDB required. +.TP +\fB\-\-fullLBA\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA registers for +sending a raw SATA command. This will be interpretted as a 48 bit value +to put into the appropriate LBA registers. This option is more useful when specifying +an LBA value for a command like a read or a write. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-lbaHigh\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA high (Cylinder High) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-lbaHighExt\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA high ext (Cylinder High) ext register for +sending a raw SATA command. This is for 48 bit commands. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-lbaLow\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA low (sector number) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-lbaLowExt\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA low ext (sector number ext) register for +sending a raw SATA command. This is for 48 bit commands. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-lbaMode\fR +(SATA Only) +.IP +Use this option to set the LBA Mode bit of the Device/Head register for +sending a raw SATA command. +This bit is necessary for performing read/write commands on modern drives. +NOTE: This bit will NOT be set by default since it only applies to read/write commands +.IP +but not all other commands in the ATA specifications. +.TP +\fB\-\-lbaMid\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA mid (Cylinder Low) register for +sending a raw SATA command. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-lbaMidExt\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the LBA mid ext (Cylinder Low ext) register for +sending a raw SATA command. This is for 48 bit commands. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-sectorCount\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the sector count register for +sending a raw SATA command. (Lower 8 bits on 48 bit commands) +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-sectorCountExt\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the sector count ext register for +sending a raw SATA command. (Upper 8 bits on 48 bit commands) +The value should be specified in hex as ??h or 0x?? or as a decimale value +.TP +\fB\-\-sectFull\fR [hex or decimal] +(SATA Only) +.IP +Use this option to specify the sector count and sector count ext register for +sending a raw SATA command. This will be interpretted as a 16bit value. +The value should be specified in hex as ??h or 0x?? or as a decimale value +.HP +\fB\-\-tfrByteBlock\fR [512 | logical | bytes | nodata] (SATA Only) +.IP +Use this option to specify the data transfer length +being sent or received when issuing a raw SATA command. This option must match +the definition of the command in the ATA/ACS specification. +This option must be provided before a command will be sent. +Arguments: +.IP +512 \- the data transfer is a number of 512B blocks (most commands) +logical \- data transfer is a number of logical block sizes transfers (read commands) +bytes \- the data transfer is a specific number of bytes (some legacy commands or tpsiu is used) +nodata \- no data transfer. Used on non\-data protocol commands +.IP +NOTE: All read/write commands should use "logical", all other data transfers should use 512 +.HP +\fB\-\-tfrProtocol\fR [pio | dma | udma | fpdma | ncq | nodata | reset | dmaque | diag] (SATA Only) +.IP +Use this option to specify the protocol for +sending a raw SATA command. This option must match the definition +of the command in the ATA/ACS specification. +This option must be provided before a command will be sent. +Arguments: +.IP +pio \- send as programmed IO protocol. +dma \- send as direct memory access protocol +udma \- send as ultra direct memory access protocol +fpdma/ncq \- send as first party direct memory access protocol (NCQ) +nodata \- send as non\-data protocol +reset \- send as reset protocol (ATAPI only) +dmaque \- send as direct memory access queued protocol (TCQ) +diag \- send as devie diagnostic protocol +.IP +NOTE: If a command with dma doesn't work, try udma. Some SATLs like it better. +NOTE: Most SATLs don't allow sending queued commands as pass\-through. Some OSs +.IP +also will not allow queued pass\-through commands. +.HP +\fB\-\-tfrSetChkCond\fR (SATA Only) +.IP +Use this option to set the check condition bit in the SAT CDB that may be +sent to a translator to inform it to generate a check condition and return +all task file results. +NOTE: This option may not work on all SATLs. +.TP +\fB\-\-tfrSize\fR [28 | 48 | complete] +(SATA Only) +.IP +Use this option to specify the command type: 28bit or 48bit +when issuing a raw SATA command. This option must match +the definition of the command in the ATA/ACS specification. +This option must be provided before a command will be sent. +Arguments: +.IP +28 \- the command is a 28 bit command (ex: identify, SMART) +48 \- the command is a 48 bit command (ex: read DMA ext, read log ext) +complete \- 48 bit command that also sets ICC or AUX registers. +.TP +use this to force a 32B CDB. If specifying 48 and AUX or ICC +are set, 32B CDB will automatically be generated without needing +this option explicitly set. +.TP +NOTE: complete TFR requires SAT 32B cdb, which many devices or interfaces +may not support. These commands may not be available. +.TP +\fB\-\-tfrXferLengthReg\fR [sectorCount | feature | tpsiu | nodata] +(SATA Only) +.IP +Use this option to specify the registers used to specify the length of data +being sent or received when issuing a raw SATA command. This option must match +the definition of the command in the ATA/ACS specification. +This option must be provided before a command will be sent. +Arguments: +.IP +sectorCount \- the sector count registers specify the number of blocks (most commands) +feature \- the feature registers specify the number of blocks (queued commands) +tpsiu \- a transport specific location will specify the length of the data transfer +nodata \- no data transfer. Used on non\-data protocol commands +.TP +NOTE: tpsiu is generally only seen supported on USB adapters, but not all USB SATL's +will recognize this option. +.TP +NOTE: For commands, such as identify (ECh), that transfer data, but do not specify +a value of 1 in the sector count, it is recommended that this is added +to the sector count register and and "sectorCount" is used for better +compatibility with various SATLs. +.IP +SAS Only: +========= +\fB\-\-cdb\fR [csv CDB] +.IP +Use this option to specify a specific CDB to +send to a device. The entered value must be +in comma separated value (csv) format. To +specify a value as hex, it must be either +pre\-pended with "0x" or post\-pended with +"h" or "H" +Examples: +.TP +1) inquiry: \fB\-\-cdb\fR 12h,0,0,0,60h,0 +2) inquiry: \fB\-\-cdb\fR 0x12,0,0,0,0x60,0 +3) inquiry: \fB\-\-cdb\fR 18,0,0,0,96,0 +.IP +All 3 examples send the same command to a drive +.HP +\fB\-\-cdbLen\fR [length in bytes] +.IP +Use this option to specify the length of the CDB +to send to the device. Max length is 255 +Some OS's may not support CDBs larger than 16 bytes +.IP +openSeaChest_Raw \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Raw Version: 0.9.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Raw: +.IP +Utility Version: 0.9.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 +Compiled Architecture: X86_64 +Detected Endianness: Little Endian +Compiler Used: GCC +Compiler Version: 11.4.0 +Operating System Type: Linux +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Raw +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Raw +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Raw +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Reservations.8 b/docs/man/man8/openSeaChest_Reservations.8 index 8b8fb4c6..e50d8fae 100644 --- a/docs/man/man8/openSeaChest_Reservations.8 +++ b/docs/man/man8/openSeaChest_Reservations.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Reservations:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_RESERVATIONS "1" "August 2024" "openSeaChest_Reservations ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Reservations \- manual page for openSeaChest_Reservations ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Reservations \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Reservations Version: 0.2.1\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Reservations Version: 0.3.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user .PP ========================================================================================== Usage @@ -372,15 +372,36 @@ capabilities for a device. NOTE: Older device supporting SPC or SPC2 may not support showing capabilities, but do support persistent reservations. .IP -Utility Version: 0.2.1 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Reservations \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Reservations Version: 0.3.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Reservations: +.IP +Utility Version: 0.3.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Reservations +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Reservations +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Reservations +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_SMART.8 b/docs/man/man8/openSeaChest_SMART.8 index deebf6d0..60f2037d 100644 --- a/docs/man/man8/openSeaChest_SMART.8 +++ b/docs/man/man8/openSeaChest_SMART.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_SMART:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_SMART "1" "August 2024" "openSeaChest_SMART ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_SMART \- manual page for openSeaChest_SMART ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_SMART \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_SMART Version: 2.3.2\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:15 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_SMART Version: 2.5.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user .PP ========================================================================================== Usage @@ -442,6 +442,19 @@ Note: This command is declared obsolete in ACS4. .IP Use this option to enable or disable SMART auto\-off\-line feature on an ATA drive. +.TP +\fB\-\-shortDST\fR +(SATA Only) +.IP +Execute the SMART off\-line data collection routine on an ATA drive. +This will run for the amount of time the device specifies that this +operation will take to complete. Progress updates are not available +while this is running. Some drives allow other commands to be processed +and some require no interruption while this routine completes. +This routine does vendor unique activities to update the SMART data and +SMART attributes the device reports. +If the SMART auto\-off\-line feature is supported and enabled, then this +routine is already running automatically in the background periodically. .HP \fB\-\-showSMARTErrorLog\fR [ summary | comprehensive ] (SATA Only) .IP @@ -532,15 +545,36 @@ error if possible. This continues until all errors reported by DST are fixed, or when the error limit is reached. The default limit is 50 errors. .IP -Utility Version: 2.3.2 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_SMART \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_SMART Version: 2.5.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_SMART: +.IP +Utility Version: 2.5.1 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_SMART +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_SMART +programs are properly installed at your site, the command +.IP +.B info openSeaChest_SMART +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_Security.8 b/docs/man/man8/openSeaChest_Security.8 index f08ec3bc..1281edc7 100644 --- a/docs/man/man8/openSeaChest_Security.8 +++ b/docs/man/man8/openSeaChest_Security.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_Security:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_SECURITY "1" "August 2024" "openSeaChest_Security ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_Security \- manual page for openSeaChest_Security ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_Security \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_Security Version: 3.3.0\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:14 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Security Version: 3.4.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user .PP ========================================================================================== Usage @@ -380,15 +380,36 @@ user data with a vendor specific pattern. Some Seagate Instant Secure Erase will perform a cryptographic erase instead of an overwrite. .IP -Utility Version: 3.3.0 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_Security \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_Security Version: 3.4.1\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143606 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_Security: +.IP +Utility Version: 3.4.1 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_Security +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_Security +programs are properly installed at your site, the command +.IP +.B info openSeaChest_Security +.PP +should give you access to the complete manual. diff --git a/docs/man/man8/openSeaChest_ZBD.8 b/docs/man/man8/openSeaChest_ZBD.8 index 08a39fef..a6bcabb5 100644 --- a/docs/man/man8/openSeaChest_ZBD.8 +++ b/docs/man/man8/openSeaChest_ZBD.8 @@ -1,15 +1,15 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH VERSION "8" "December 2023" "Version Info for openSeaChest_ZBD:" "System Administration Utilities" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. +.TH OPENSEACHEST_ZBD "1" "August 2024" "openSeaChest_ZBD ==========================================================================================" "User Commands" .SH NAME -Version \- =drive utilities +openSeaChest_ZBD \- manual page for openSeaChest_ZBD ========================================================================================== .SH DESCRIPTION ========================================================================================== .IP openSeaChest_ZBD \- openSeaChest drive utilities \- NVMe Enabled -Copyright (c) 2014\-2023 Seagate Technology LLC and/or its Affiliates, All Rights Reserved -openSeaChest_ZBD Version: 2.2.2\-6_2_0 X86_64 -Build Date: Dec 1 2023 -Today: Fri Dec 1 15:18:15 2023 User: current user +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_ZBD Version: 2.3.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143607 User: current user .PP ========================================================================================== Usage @@ -279,15 +279,36 @@ such as \fB\-\-reportZones\fR, \fB\-\-closeZone\fR, \fB\-\-finishZone\fR, \fB\-\ Use "all" with the options listed above to apply an action to all zones on the device. .IP -Utility Version: 2.2.2 -opensea\-common Version: 2.0.0 -opensea\-transport Version: 6.2.0 -opensea\-operations Version: 5.1.1 -Build Date: Dec 1 2023 +openSeaChest_ZBD \- openSeaChest drive utilities \- NVMe Enabled +Copyright (c) 2014\-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +openSeaChest_ZBD Version: 2.3.0\-8_0_0 X86_64 +Build Date: Aug 26 2024 +Today: 20240828T143607 User: current user +.PP +========================================================================================== +Version Info for openSeaChest_ZBD: +.IP +Utility Version: 2.3.0 +opensea\-common Version: 4.0.0 +opensea\-transport Version: 8.0.0 +opensea\-operations Version: 8.0.0 +Build Date: Aug 26 2024 Compiled Architecture: X86_64 Detected Endianness: Little Endian Compiler Used: GCC -Compiler Version: 7.5.0 +Compiler Version: 11.4.0 Operating System Type: Linux -Operating System Version: 4.15.0\-211 -Operating System Name: Ubuntu 18.04.6 LTS +Operating System Version: 5.15.153\-1 +Operating System Name: Ubuntu 22.04.4 LTS +.SH "SEE ALSO" +The full documentation for +.B openSeaChest_ZBD +is maintained as a Texinfo manual. If the +.B info +and +.B openSeaChest_ZBD +programs are properly installed at your site, the command +.IP +.B info openSeaChest_ZBD +.PP +should give you access to the complete manual. diff --git a/docs/openSeaChest/openSeaChest_Basics_Version_History.txt b/docs/openSeaChest/openSeaChest_Basics_Version_History.txt index 8f8a2702..1b39ce93 100644 --- a/docs/openSeaChest/openSeaChest_Basics_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Basics_Version_History.txt @@ -262,4 +262,20 @@ v3.5.4 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v3.6.2 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Fixed capacity output after changing MaxLBA value on SATA and SAS. + dded new options to change a device's MN when changing the maxLBA to. + This new feature is supported only on new products with ACS-6 + that support changing the MN. A log page describes the other MN's + available at different capacities that can be used. + Fixed memory leak in --progress option. + All config files and firmware files must now be loaded from secured directories. + Secured directories are owned by the user or root and do not allow writing to other users/groups. + Fixed incorrect parameter for activate option. Backwards compatibility in + the API was able to catch this without causing an error. + Added SMART trip reason when SMART trip is detected (As SeaChest_SMART has). + Improved SMART trip detection algorithm when smart return status command + is not available and attributes and thresholds must be used instead. + SMART trip warning is now formatted according to text from SFF-8055. diff --git a/docs/openSeaChest/openSeaChest_Configure_Version_History.txt b/docs/openSeaChest/openSeaChest_Configure_Version_History.txt index 3a2e84ab..8673ed01 100644 --- a/docs/openSeaChest/openSeaChest_Configure_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Configure_Version_History.txt @@ -188,3 +188,16 @@ v2.5.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v2.7.1 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Added new options to change a device's MN when changing the maxLBA to. + This new feature is supported only on new products with ACS-6 + that support changing the MN. A log page describes the other MN's + available at different capacities that can be used. + Updated PUIS feature set options. Note: This will be removed from + configure and is available in PowerControl going forward. + Added options to configure ATA Write-read-verify feature. + Changing SCSI Mode pages from a file now requires secured directories. + These directories (and those above it) must only be available to the user/root/admin + and not writable by other users or groups. + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_Defect_About.txt b/docs/openSeaChest/openSeaChest_Defect_About.txt new file mode 100644 index 00000000..eee38909 --- /dev/null +++ b/docs/openSeaChest/openSeaChest_Defect_About.txt @@ -0,0 +1,74 @@ +Welcome to Seagate's openSeaChest Defect diagnostic software. + +This User Guide file contains important information about openSeaChest Defect. +Please read this entire file before using this software. + +openSeaChest is a comprehensive, easy-to-use command line diagnostic tool that +helps you quickly determine the health and status of your Seagate storage +product. It includes several tests that will examine the physical media on your +Seagate, Samsung or Maxtor disk drive. + +openSeaChest_Defect is a utility to display standardized device defect lists +and create flagged or psuedo uncorrectable errors for testing purposes. +When creating flagged or psuedo uncorrectable errors, this will cause data loss. +These commands are meant to test a drive's defect handling capabilities as well +as how a file system may react to defects on the device. + +Tests and commands which are completely data safe will run on any disk drive. +Tests and commands which change the drive (like firmware download or data +erasure or setting the maximum capacity, etc) are limited to Seagate disk +drives (this includes Seagate, Maxtor, Samsung and LaCie). Be careful using +openSeaChest because some of the features, like the data erasure options, will +cause data loss. Seagate is not responsible for lost user data. + +If this is your drive, you should always keep a current backup of your +important data. + +Important note: Many tests in this tool directly reference storage device data +sectors, also known as Logical Block Addresses (LBA). Test arguments may +require a starting LBA or an LBA range. The predefined variable 'maxLBA' +refers to the last sector on the drive. Many older SATA and SAS storage +controllers (also known as Host Bus Adapters [HBA]) have a maximum addressable +limit of 4294967295 [FFFFh] LBAs hard wired into their design. This equates to +2.1TB using 512 byte sectors. This also means accessing an LBA beyond the +2.1TB limitation either will result in an error or simply the last readable LBA +(usually LBA 4294967295 [FFFFh]) depending on the actual hardware. This +limitation can have important consequences. For example, if you intended to +erase a 4TB drive, then only the first 2TB will actually get erased (or maybe +even twice!) and the last 2TB will remain untouched. You should carefully +evaluate your system hardware to understand if your storage controllers provide +support for greater than 2.1TB. + +Note: One gigabyte, or GB, equals one billion bytes when referring to hard +drive capacity. This software may use information provided by the operating +system to display capacity and volume size. The Windows file system uses a +binary calculation for gibibyte or GiB (2^30) which causes the abbreviated size +to appear smaller. The total number of bytes on a disk drive divided by the +decimal calculation for gigabyte or GB (10^9) shows the expected abbreviated +size. See this FAQ for more information +<http://knowledge.seagate.com/articles/en_US/FAQ/172191en?language=en_US>. + +NOTE: Windows severely restricts downloading firmware to SATA drives. Please +see the section below "Windows Restrictions Over SATA Firmware Downloads". +openSeaChest_Basics may not be fully functional on non-Seagate drives. + +Usage - Linux (run with sudo) +============================= + openSeaChest_Defect [-d <sg_device>] {arguments} {options} + +Examples - Linux +================ + sudo openSeaChest_Defect --scan + sudo openSeaChest_Defect -d /dev/sg2 -i + sudo openSeaChest_Defect -d /dev/sg1 --shortDST --poll + +Usage - Windows (run as administrator) +====================================== + openSeaChest_Defect [-d <PD_device>] {arguments} {options} + +Examples - Windows +================== + openSeaChest_Defect --scan + openSeaChest_Defect -d PD0 -i + openSeaChest_Defect -d PD1 --shortDST --poll + diff --git a/docs/openSeaChest/openSeaChest_Defect_Version_History.txt b/docs/openSeaChest/openSeaChest_Defect_Version_History.txt new file mode 100644 index 00000000..6043f503 --- /dev/null +++ b/docs/openSeaChest/openSeaChest_Defect_Version_History.txt @@ -0,0 +1,6 @@ +=============== +Version History - openSeaChest_Defect +=============== +v0.9.0 28-Aug-2024 Combined 2 internal tools and moved them to openSeaChest_Defect + Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) diff --git a/docs/openSeaChest/openSeaChest_Erase_Version_History.txt b/docs/openSeaChest/openSeaChest_Erase_Version_History.txt index e173f753..e20bba22 100644 --- a/docs/openSeaChest/openSeaChest_Erase_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Erase_Version_History.txt @@ -241,3 +241,24 @@ v4.3.6 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v4.6.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Refactored Sanitize option parsing and handling. + Handle SCSI unique sanitize conditions like write after crypto/block erase + and how PI fields may be invalid after these operations which affects OS + read commands to suggest a user also perform a overwrite. + Added --znr (Zone no reset) and --noDeallocate options for ZBDs and NVMe + devices with Sanitize and ATA security erase to allow for better erase + verification. + Added options to specify number of overwrite passes in Sanitize overwrite + as well as option to invert the patter between overwrite passes. + Added option to allow running sanitize in unrestricted mode. + Better handling for sanitize if in a failure condition to continue/retry a + sanitize operation in failed state instead of exiting. + Changed refresh FS system behavior to only run when utility knows erase fully completed + Added ability to manually refresh file systems from cli option. + Improved sanitization of ATA security erase password after it is done being + used to make sure it is also removed from memory. + Improved logic within --eraseRestoreMaxPrep to handle a few other cases and + feature set interactions that were not previously handled. + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_Firmware_Version_History.txt b/docs/openSeaChest/openSeaChest_Firmware_Version_History.txt index 745b42e8..8d2cc2f2 100644 --- a/docs/openSeaChest/openSeaChest_Firmware_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Firmware_Version_History.txt @@ -204,4 +204,12 @@ v4.0.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. Workaround for some SAS drives on some HBAs reporting incorrect response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report - all zeroes instead of expected output in RTFRs. \ No newline at end of file + all zeroes instead of expected output in RTFRs. +v4.2.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + All firmware files must now be loaded from secured directories. + Secured directories are owned by the user or root and do not allow writing to other users/groups. + Fixed incorrect parameter for activate option. Backwards compatibility in + the API was able to catch this without causing an error. + Added show SCSI FW info option which is based on Seagate's public + SCSI commands reference manual and show more fields unique to Seagate firmware. diff --git a/docs/openSeaChest/openSeaChest_Format_Version_History.txt b/docs/openSeaChest/openSeaChest_Format_Version_History.txt index 9b9c11f7..efe53cdf 100644 --- a/docs/openSeaChest/openSeaChest_Format_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Format_Version_History.txt @@ -180,3 +180,10 @@ v3.0.4 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v3.2.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Added secure file API for reading pattern to use for formatting when user + is providing a custom pattern to use for a format unit on SAS. + Added --force as option to pass with --setSectorSize to force retries + or attempt the commands to change sector size or recovery from bad formats. + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_GenericTests_Version_History.txt b/docs/openSeaChest/openSeaChest_GenericTests_Version_History.txt index a69e588e..5760eee3 100644 --- a/docs/openSeaChest/openSeaChest_GenericTests_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_GenericTests_Version_History.txt @@ -199,3 +199,7 @@ v2.2.2 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v2.3.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Fixed a bug in getting NVMe block size which may cause occasional crashes on + drives with more than 16 formats supported. \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_Info_Version_History.txt b/docs/openSeaChest/openSeaChest_Info_Version_History.txt index 9ebd0f28..9323d67e 100644 --- a/docs/openSeaChest/openSeaChest_Info_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Info_Version_History.txt @@ -171,3 +171,7 @@ v2.5.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v2.7.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Added Seagate vendor unique device statistics to output of --deviceStatistics + Added option to show SATA Phy event counters \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_Logs_Version_History.txt b/docs/openSeaChest/openSeaChest_Logs_Version_History.txt index 1760295b..233bf188 100644 --- a/docs/openSeaChest/openSeaChest_Logs_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Logs_Version_History.txt @@ -50,4 +50,12 @@ v2.4.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. Workaround for some SAS drives on some HBAs reporting incorrect response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report - all zeroes instead of expected output in RTFRs. \ No newline at end of file + all zeroes instead of expected output in RTFRs. +v2.5.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + Fixed bug in generating log file names which could sometimes come out + as (null) in the path. + All log files can only be saved in secure directories. Directories must be + owned by the user/root/admin and not write accessible by others. + This rule applies to all directories above the output directory as well. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_NVMe_Version_History.txt b/docs/openSeaChest/openSeaChest_NVMe_Version_History.txt index 02bb4cba..1fcd8166 100644 --- a/docs/openSeaChest/openSeaChest_NVMe_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_NVMe_Version_History.txt @@ -95,3 +95,6 @@ v2.3.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v2.4.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Added showNVMPowerStates and listSupportedLogs options. \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_PassthroughTest_Version_History.txt b/docs/openSeaChest/openSeaChest_PassthroughTest_Version_History.txt index d945d4ce..a797c4e1 100644 --- a/docs/openSeaChest/openSeaChest_PassthroughTest_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_PassthroughTest_Version_History.txt @@ -39,4 +39,7 @@ v1.3.3 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. Workaround for some SAS drives on some HBAs reporting incorrect response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report - all zeroes instead of expected output in RTFRs. \ No newline at end of file + all zeroes instead of expected output in RTFRs. +v1.4.1 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_PowerControl_Version_History.txt b/docs/openSeaChest/openSeaChest_PowerControl_Version_History.txt index b3e4b10e..7a919da7 100644 --- a/docs/openSeaChest/openSeaChest_PowerControl_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_PowerControl_Version_History.txt @@ -230,4 +230,8 @@ v3.4.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. Workaround for some SAS drives on some HBAs reporting incorrect response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report - all zeroes instead of expected output in RTFRs. \ No newline at end of file + all zeroes instead of expected output in RTFRs. +v3.6.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Added option to see PUIS info and change PUIS settings. + diff --git a/docs/openSeaChest/openSeaChest_Raw_About.txt b/docs/openSeaChest/openSeaChest_Raw_About.txt new file mode 100644 index 00000000..50040e2b --- /dev/null +++ b/docs/openSeaChest/openSeaChest_Raw_About.txt @@ -0,0 +1,77 @@ +Welcome to Seagate's openSeaChest Raw diagnostic software. + +This User Guide file contains important information about openSeaChest Raw. +Please read this entire file before using this software. + +openSeaChest is a comprehensive, easy-to-use command line diagnostic tool that +helps you quickly determine the health and status of your Seagate storage +product. It includes several tests that will examine the physical media on your +Seagate, Samsung or Maxtor disk drive. + +openSeaChest_Raw is a utility designed to allow specifying commands to run in raw mode. +Both CDB's and TFRs can be specified to build and issue a command. +TFR's are only supported by ATA devices and will be passed through a SAT CDB maker +for you based on the inputs provided to make sure the command is issued in +any hardware configuration. +Any CDB from a T10 standard can be issued using this utility. +Most TFR commands can be issued, however asynchronous commands will likely +be blocked by the OS, a driver, or an HBA. + +Tests and commands which are completely data safe will run on any disk drive. +Tests and commands which change the drive (like firmware download or data +erasure or setting the maximum capacity, etc) are limited to Seagate disk +drives (this includes Seagate, Maxtor, Samsung and LaCie). Be careful using +openSeaChest because some of the features, like the data erasure options, will +cause data loss. Seagate is not responsible for lost user data. + +If this is your drive, you should always keep a current backup of your +important data. + +Important note: Many tests in this tool directly reference storage device data +sectors, also known as Logical Block Addresses (LBA). Test arguments may +require a starting LBA or an LBA range. The predefined variable 'maxLBA' +refers to the last sector on the drive. Many older SATA and SAS storage +controllers (also known as Host Bus Adapters [HBA]) have a maximum addressable +limit of 4294967295 [FFFFh] LBAs hard wired into their design. This equates to +2.1TB using 512 byte sectors. This also means accessing an LBA beyond the +2.1TB limitation either will result in an error or simply the last readable LBA +(usually LBA 4294967295 [FFFFh]) depending on the actual hardware. This +limitation can have important consequences. For example, if you intended to +erase a 4TB drive, then only the first 2TB will actually get erased (or maybe +even twice!) and the last 2TB will remain untouched. You should carefully +evaluate your system hardware to understand if your storage controllers provide +support for greater than 2.1TB. + +Note: One gigabyte, or GB, equals one billion bytes when referring to hard +drive capacity. This software may use information provided by the operating +system to display capacity and volume size. The Windows file system uses a +binary calculation for gibibyte or GiB (2^30) which causes the abbreviated size +to appear smaller. The total number of bytes on a disk drive divided by the +decimal calculation for gigabyte or GB (10^9) shows the expected abbreviated +size. See this FAQ for more information +<http://knowledge.seagate.com/articles/en_US/FAQ/172191en?language=en_US>. + +NOTE: Windows severely restricts downloading firmware to SATA drives. Please +see the section below "Windows Restrictions Over SATA Firmware Downloads". +openSeaChest_Basics may not be fully functional on non-Seagate drives. + +Usage - Linux (run with sudo) +============================= + openSeaChest_Raw [-d <sg_device>] {arguments} {options} + +Examples - Linux +================ + sudo openSeaChest_Raw --scan + sudo openSeaChest_Raw -d /dev/sg2 -i + sudo openSeaChest_Raw -d /dev/sg1 --shortDST --poll + +Usage - Windows (run as administrator) +====================================== + openSeaChest_Basics [-d <PD_device>] {arguments} {options} + +Examples - Windows +================== + openSeaChest_Raw --scan + openSeaChest_Raw -d PD0 -i + openSeaChest_Raw -d PD1 --shortDST --poll + diff --git a/docs/openSeaChest/openSeaChest_Raw_Version_History.txt b/docs/openSeaChest/openSeaChest_Raw_Version_History.txt new file mode 100644 index 00000000..d71b3504 --- /dev/null +++ b/docs/openSeaChest/openSeaChest_Raw_Version_History.txt @@ -0,0 +1,8 @@ +=============== +Version History - openSeaChest_Raw +=============== +v0.9.0 28-Aug-2024 Combined 2 internal tools and moved them to openSeaChest_Raw + Internal tools were separate for CDB and TFR so they were + combined to simplify things a bit. + Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) diff --git a/docs/openSeaChest/openSeaChest_Reservations_Version_History.txt b/docs/openSeaChest/openSeaChest_Reservations_Version_History.txt index 7df5de8d..ffcd5b42 100644 --- a/docs/openSeaChest/openSeaChest_Reservations_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Reservations_Version_History.txt @@ -1,4 +1,7 @@ =============== Version History - openSeaChest_Reservations =============== -TODO: Review past releases and recreate version history \ No newline at end of file +v0.0.3 01-May-2021 Initial release of openSeaChest_Reservations utility. +v0.2.1 01-May-2023 Nobanner, fast discovery, lowlevel info options added. +v0.3.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_SMART_Version_History.txt b/docs/openSeaChest/openSeaChest_SMART_Version_History.txt index fd827976..de8630a1 100644 --- a/docs/openSeaChest/openSeaChest_SMART_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_SMART_Version_History.txt @@ -213,3 +213,12 @@ v2.3.2 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v2.5.1 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Added old SMART offline scan routine as an option. + Fixed how SMART trip reason is displayed. + Improved SMART trip detection algorithm when smart return status command + is not available and attributes and thresholds must be used instead. + SMART trip warning is now formatted according to text from SFF-8055. + Fixed a memory leak from the --progress option + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_Security_Version_History.txt b/docs/openSeaChest/openSeaChest_Security_Version_History.txt index b9318e15..08d59380 100644 --- a/docs/openSeaChest/openSeaChest_Security_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_Security_Version_History.txt @@ -193,3 +193,9 @@ v3.3.0 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report all zeroes instead of expected output in RTFRs. +v3.4.1 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + Improved memory sanitization for provided ATA security password when + the software is done using the password to ensure it has been deleted + from memory. + \ No newline at end of file diff --git a/docs/openSeaChest/openSeaChest_ZBD_Version_History.txt b/docs/openSeaChest/openSeaChest_ZBD_Version_History.txt index c3d1135c..77ea840e 100644 --- a/docs/openSeaChest/openSeaChest_ZBD_Version_History.txt +++ b/docs/openSeaChest/openSeaChest_ZBD_Version_History.txt @@ -165,4 +165,7 @@ v2.2.2 01-Dec-2023 Updated to newer opensea-libs to pull in low-level fixes. Workaround for some SAS drives on some HBAs reporting incorrect response to SAT A1h CDB. Fixed a bug in FreeBSD causing non-data ATA commands to report - all zeroes instead of expected output in RTFRs. \ No newline at end of file + all zeroes instead of expected output in RTFRs. +v2.3.0 28-Aug-2024 Pull in security updates and low-level bug fixes from opensea-libs. + CISS RAID device support for Linux (CCISS, HPSA, and SmartPQI drivers) + \ No newline at end of file diff --git a/include/EULA.h b/include/EULA.h index 3b007a97..2588c087 100644 --- a/include/EULA.h +++ b/include/EULA.h @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/include/openseachest_util_options.h b/include/openseachest_util_options.h index 2e72398c..f0f28110 100644 --- a/include/openseachest_util_options.h +++ b/include/openseachest_util_options.h @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -29,13 +30,15 @@ extern "C" { #endif - #include "common.h" -#include "opensea_common_version.h" -#include "opensea_operation_version.h" + #include "common_types.h" + #include "opensea_common_version.h" + #include "opensea_operation_version.h" + #include "secure_file.h" + #include "common_public.h" //this is being defined for using bools with getopt since using a bool (1 byte typically) will cause stack corruption at runtime //This type should only be used where a boolean is desired when using the getopt parser (which expects an int), otherwise bool will do just fine - #define getOptBool int + typedef int getOptBool; #define goFalse 0 #define goTrue !goFalse #define CURRENT_YEAR_LENGTH 5 @@ -52,8 +55,8 @@ extern "C" UTIL_EXIT_CANNOT_OPEN_FILE, UTIL_EXIT_FILE_ALREADY_EXISTS, UTIL_EXIT_NEED_ELEVATED_PRIVILEGES, - UTIL_EXIT_NOT_ENOUGH_RESOURCES, - //TODO: More generic exit codes go here + UTIL_EXIT_NOT_ENOUGH_RESOURCES, + //More generic exit codes go here UTIL_EXIT_ERROR_WRITING_FILE, //added 5/19/20 //Tool specific exit codes go here UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE = 32,//Use this value in a tool to start the tool's specific error code enumeration @@ -75,26 +78,42 @@ extern "C" #define HANDLE_LIST deviceHandleList #define DEVICE_UTIL_VARS \ bool RUN_ON_ALL_DRIVES = false;\ - tDevice *DEVICE_LIST = NULL;\ + tDevice *DEVICE_LIST = M_NULLPTR;\ uint32_t DEVICE_LIST_COUNT = 0;\ bool USER_PROVIDED_HANDLE = false;\ - char **HANDLE_LIST = NULL; + char **HANDLE_LIST = M_NULLPTR; #define DEVICE_SHORT_OPT 'd' #define DEVICE_LONG_OPT_STRING "device" - #define DEVICE_LONG_OPT { DEVICE_LONG_OPT_STRING, required_argument, NULL, DEVICE_SHORT_OPT } + #define DEVICE_LONG_OPT { DEVICE_LONG_OPT_STRING, required_argument, M_NULLPTR, DEVICE_SHORT_OPT } + + //NOTE: This is to clean up the single allocation in the utility layer before it exits - TJE + static M_INLINE void free_device_list(tDevice **list) + { + safe_Free(M_REINTERPRET_CAST(void**, list)); + } #define SHOW_HELP_FLAG showHelp #define SHOW_HELP_VAR bool SHOW_HELP_FLAG = false; #define HELP_SHORT_OPT 'h' #define HELP_LONG_OPT_STRING "help" - #define HELP_LONG_OPT { HELP_LONG_OPT_STRING, no_argument, NULL, HELP_SHORT_OPT } + #define HELP_LONG_OPT { HELP_LONG_OPT_STRING, no_argument, M_NULLPTR, HELP_SHORT_OPT } #define DEVICE_INFO_FLAG devInfo #define DEVICE_INFO_VAR bool DEVICE_INFO_FLAG = false; #define DEVICE_INFO_SHORT_OPT 'i' #define DEVICE_INFO_LONG_OPT_STRING "deviceInfo" - #define DEVICE_INFO_LONG_OPT { DEVICE_INFO_LONG_OPT_STRING, no_argument, NULL, DEVICE_INFO_SHORT_OPT } + #define DEVICE_INFO_LONG_OPT { DEVICE_INFO_LONG_OPT_STRING, no_argument, M_NULLPTR, DEVICE_INFO_SHORT_OPT } + #define CAPACITY_MODEL_NUMBER_MAPPING_FLAG capModelMapping + #define CAPACITY_MODEL_NUMBER_MAPPING_VAR getOptBool CAPACITY_MODEL_NUMBER_MAPPING_FLAG = false; + #define CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT_STRING "capacityModelNumberMapping" + #define CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT { CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT_STRING, no_argument, &CAPACITY_MODEL_NUMBER_MAPPING_FLAG, goTrue } + + #define CHANGE_ID_STRING_FLAG changeIdString + #define CHANGE_ID_STRING_VAR getOptBool CHANGE_ID_STRING_FLAG = goFalse; + #define CHANGE_ID_STRING_LONG_OPT_STRING "changeIdString" + #define CHANGE_ID_STRING_LONG_OPT { CHANGE_ID_STRING_LONG_OPT_STRING, no_argument, &CHANGE_ID_STRING_FLAG, goTrue } + #define PARTITION_INFO_FLAG showPartitionInfo #define PARTITION_INFO_VAR getOptBool PARTITION_INFO_FLAG = goFalse; #define PARTITION_INFO_LONG_OPT_STRING "partitionInfo" @@ -121,47 +140,49 @@ extern "C" #define SCAN_FLAG_VAR bool SCAN_FLAG = false; #define SCAN_SHORT_OPT 's' #define SCAN_LONG_OPT_STRING "scan" - #define SCAN_LONG_OPT { SCAN_LONG_OPT_STRING, no_argument, NULL, SCAN_SHORT_OPT } + #define SCAN_LONG_OPT { SCAN_LONG_OPT_STRING, no_argument, M_NULLPTR, SCAN_SHORT_OPT } #define AGRESSIVE_SCAN_FLAG agressiveScan #define AGRESSIVE_SCAN_FLAG_VAR bool AGRESSIVE_SCAN_FLAG = false; #define AGRESSIVE_SCAN_SHORT_OPT 'S' #define AGRESSIVE_SCAN_LONG_OPT_STRING "Scan" - #define AGRESSIVE_SCAN_LONG_OPT { AGRESSIVE_SCAN_LONG_OPT_STRING, no_argument, NULL, AGRESSIVE_SCAN_SHORT_OPT } + #define AGRESSIVE_SCAN_LONG_OPT { AGRESSIVE_SCAN_LONG_OPT_STRING, no_argument, M_NULLPTR, AGRESSIVE_SCAN_SHORT_OPT } #define SCAN_FLAGS_SHORT_OPT 'F' #define SCAN_FLAGS_LONG_OPT_STRING "scanFlags" - #define SCAN_FLAGS_LONG_OPT { SCAN_FLAGS_LONG_OPT_STRING, required_argument, NULL, SCAN_FLAGS_SHORT_OPT } + #define SCAN_FLAGS_LONG_OPT { SCAN_FLAGS_LONG_OPT_STRING, required_argument, M_NULLPTR, SCAN_FLAGS_SHORT_OPT } - #define NO_BANNER_FLAG noBanner - #define NO_BANNER_VAR getOptBool NO_BANNER_FLAG = goFalse; - #define NO_BANNER_OPT_STRING "noBanner" - #define NO_BANNER_OPT { NO_BANNER_OPT_STRING, no_argument, &NO_BANNER_FLAG, goTrue} + #define NO_BANNER_FLAG noBanner + #define NO_BANNER_VAR getOptBool NO_BANNER_FLAG = goFalse; + #define NO_BANNER_OPT_STRING "noBanner" + #define NO_BANNER_OPT { NO_BANNER_OPT_STRING, no_argument, &NO_BANNER_FLAG, goTrue} #define SHOW_BANNER_FLAG showBanner #define SHOW_BANNER_VAR bool SHOW_BANNER_FLAG = false; #define VERSION_SHORT_OPT 'V' #define VERSION_LONG_OPT_STRING "version" - #define VERSION_LONG_OPT { VERSION_LONG_OPT_STRING, no_argument, NULL, VERSION_SHORT_OPT } + #define VERSION_LONG_OPT { VERSION_LONG_OPT_STRING, no_argument, M_NULLPTR, VERSION_SHORT_OPT } #define VERBOSE_SHORT_OPT 'v' #define VERBOSE_LONG_OPT_STRING "verbose" - #define VERBOSE_LONG_OPT { VERBOSE_LONG_OPT_STRING, required_argument, NULL, VERBOSE_SHORT_OPT } + #define VERBOSE_LONG_OPT { VERBOSE_LONG_OPT_STRING, required_argument, M_NULLPTR, VERBOSE_SHORT_OPT } + + M_NODISCARD bool set_Verbosity_From_String(const char* requestedLevel, eVerbosityLevels* verbosity); #define QUIET_SHORT_OPT 'q' #define QUIET_LONG_OPT_STRING "quiet" - #define QUIET_LONG_OPT { QUIET_LONG_OPT_STRING, no_argument, NULL, QUIET_SHORT_OPT } + #define QUIET_LONG_OPT { QUIET_LONG_OPT_STRING, no_argument, M_NULLPTR, QUIET_SHORT_OPT } #define TEST_UNIT_READY_FLAG sendTestUnitReady #define TEST_UNIT_READY_VAR getOptBool TEST_UNIT_READY_FLAG = goFalse; #define TEST_UNIT_READY_LONG_OPT_STRING "testUnitReady" #define TEST_UNIT_READY_LONG_OPT { TEST_UNIT_READY_LONG_OPT_STRING, no_argument, &TEST_UNIT_READY_FLAG, goTrue } - #define FAST_DISCOVERY_FLAG fastDiscovery - #define FAST_DISCOVERY_VAR \ - getOptBool FAST_DISCOVERY_FLAG = goFalse; - #define FAST_DISCOVERY_LONG_OPT_STRING "fastDiscovery" - #define FAST_DISCOVERY_LONG_OPT { FAST_DISCOVERY_LONG_OPT_STRING, no_argument, &FAST_DISCOVERY_FLAG, goTrue } + #define FAST_DISCOVERY_FLAG fastDiscovery + #define FAST_DISCOVERY_VAR \ + getOptBool FAST_DISCOVERY_FLAG = goFalse; + #define FAST_DISCOVERY_LONG_OPT_STRING "fastDiscovery" + #define FAST_DISCOVERY_LONG_OPT { FAST_DISCOVERY_LONG_OPT_STRING, no_argument, &FAST_DISCOVERY_FLAG, goTrue } #define ONLY_SEAGATE_FLAG onlySeagateDrives #define ONLY_SEAGATE_VAR getOptBool ONLY_SEAGATE_FLAG = goFalse; @@ -170,12 +191,14 @@ extern "C" #define FORCE_SCSI_FLAG forceSCSI #define FORCE_ATA_FLAG forceATA + #define FORCE_NVME_FLAG forceNVME #define FORCE_ATA_PIO_FLAG forcePIOATA #define FORCE_ATA_DMA_FLAG forceATADMA #define FORCE_ATA_UDMA_FLAG forceATAUDMA #define FORCE_DRIVE_TYPE_VARS\ getOptBool FORCE_SCSI_FLAG = goFalse;\ getOptBool FORCE_ATA_FLAG = goFalse;\ + getOptBool FORCE_NVME_FLAG = goFalse;\ getOptBool FORCE_ATA_PIO_FLAG = goFalse;\ getOptBool FORCE_ATA_DMA_FLAG = goFalse;\ getOptBool FORCE_ATA_UDMA_FLAG = goFalse; @@ -183,6 +206,8 @@ extern "C" #define FORCE_SCSI_LONG_OPT { FORCE_SCSI_LONG_OPT_STRING, no_argument, &FORCE_SCSI_FLAG, goTrue } #define FORCE_ATA_LONG_OPT_STRING "forceATA" #define FORCE_ATA_LONG_OPT { FORCE_ATA_LONG_OPT_STRING, no_argument, &FORCE_ATA_FLAG, goTrue } + #define FORCE_NVME_LONG_OPT_STRING "forceNVME" + #define FORCE_NVME_LONG_OPT { FORCE_NVME_LONG_OPT_STRING, no_argument, &FORCE_NVME_FLAG, goTrue } #define FORCE_ATA_PIO_LONG_OPT_STRING "forceATAPIO" #define FORCE_ATA_PIO_LONG_OPT { FORCE_ATA_PIO_LONG_OPT_STRING, no_argument, &FORCE_ATA_PIO_FLAG, goTrue } #define FORCE_ATA_DMA_LONG_OPT_STRING "forceATADMA" @@ -190,7 +215,7 @@ extern "C" #define FORCE_ATA_UDMA_LONG_OPT_STRING "forceATAUDMA" #define FORCE_ATA_UDMA_LONG_OPT { FORCE_ATA_UDMA_LONG_OPT_STRING, no_argument, &FORCE_ATA_UDMA_FLAG, goTrue } #define FORCE_DRIVE_TYPE_LONG_OPTS \ - FORCE_SCSI_LONG_OPT, FORCE_ATA_LONG_OPT, FORCE_ATA_PIO_LONG_OPT, FORCE_ATA_DMA_LONG_OPT, FORCE_ATA_UDMA_LONG_OPT + FORCE_SCSI_LONG_OPT, FORCE_ATA_LONG_OPT, FORCE_NVME_LONG_OPT, FORCE_ATA_PIO_LONG_OPT, FORCE_ATA_DMA_LONG_OPT, FORCE_ATA_UDMA_LONG_OPT #define USE_MAX_LBA useMaxLBA #define USE_CHILD_MAX_LBA useChildMaxLBA @@ -204,22 +229,22 @@ extern "C" uint64_t DISPLAY_LBA_THE_LBA = UINT64_MAX;\ bool DISPLAY_LBA_FLAG = false; #define DISPLAY_LBA_LONG_OPT_STRING "displayLBA" - #define DISPLAY_LBA_LONG_OPT { DISPLAY_LBA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define DISPLAY_LBA_LONG_OPT { DISPLAY_LBA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define PATTERN_BUFFER patternBuffer #define PATTERN_FLAG usePattern #define PATTERN_BUFFER_LENGTH 8192 #define PATTERN_VARS\ bool PATTERN_FLAG = false;\ - uint8_t PATTERN_BUFFER[PATTERN_BUFFER_LENGTH] = { 0 };/*Allocating 2 * current largest logical sector (4096) for now...-TJE */ + DECLARE_ZERO_INIT_ARRAY(uint8_t, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH);/*Allocating 2 * current largest logical sector (4096) for now...-TJE */ #define PATTERN_LONG_OPT_STRING "pattern" - #define PATTERN_LONG_OPT { PATTERN_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PATTERN_LONG_OPT { PATTERN_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define OUTPUTPATH_FLAG outputPathPtr - #define OUTPUTPATH_VAR char *OUTPUTPATH_FLAG = NULL; + #define OUTPUTPATH_VAR char *OUTPUTPATH_FLAG = M_NULLPTR; #define PATH_LONG_OPT_STRING "outputPath" - #define OUTPUTPATH_LONG_OPT { PATH_LONG_OPT_STRING, required_argument, NULL, 0} + #define OUTPUTPATH_LONG_OPT { PATH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0} #define LICENSE_FLAG showLicense #define LICENSE_VAR getOptBool LICENSE_FLAG = goFalse; @@ -237,10 +262,10 @@ extern "C" #define POLL_LONG_OPT { POLL_LONG_OPT_STRING, no_argument, &POLL_FLAG, goTrue } #define PROGRESS_CHAR progressTest - #define PROGRESS_VAR char *PROGRESS_CHAR = NULL; + #define PROGRESS_VAR char *PROGRESS_CHAR = M_NULLPTR; #define PROGRESS_SHORT_OPT '%' #define PROGRESS_LONG_OPT_STRING "progress" - #define PROGRESS_LONG_OPT { PROGRESS_LONG_OPT_STRING, required_argument, NULL, PROGRESS_SHORT_OPT } + #define PROGRESS_LONG_OPT { PROGRESS_LONG_OPT_STRING, required_argument, M_NULLPTR, PROGRESS_SHORT_OPT } #define DATA_ERASE_ACCEPT_STRING "this-will-erase-data" #define POSSIBLE_DATA_ERASE_ACCEPT_STRING "this-may-erase-data" @@ -259,7 +284,7 @@ extern "C" #define SINGLE_SECTOR_DATA_ERASE_FLAG singleSectorDataEraseAccepted #define SINGLE_SECTOR_DATA_ERASE_VAR bool SINGLE_SECTOR_DATA_ERASE_FLAG = false; #define CONFIRM_LONG_OPT_STRING "confirm" - #define CONFIRM_LONG_OPT { CONFIRM_LONG_OPT_STRING, required_argument, NULL, 0} + #define CONFIRM_LONG_OPT { CONFIRM_LONG_OPT_STRING, required_argument, M_NULLPTR, 0} //SMART related options #define SMART_CHECK_FLAG smartCheck @@ -277,6 +302,11 @@ extern "C" #define SHORT_DST_LONG_OPT_STRING "shortDST" #define SHORT_DST_LONG_OPT { SHORT_DST_LONG_OPT_STRING, no_argument, &SHORT_DST_FLAG, goTrue } + #define SMART_OFFLINE_SCAN_FLAG smartOfflineScan + #define SMART_OFFLINE_SCAN_VAR getOptBool SMART_OFFLINE_SCAN_FLAG = goFalse; + #define SMART_OFFLINE_SCAN_LONG_OPT_STRING "smartOffline" + #define SMART_OFFLINE_SCAN_LONG_OPT { SMART_OFFLINE_SCAN_LONG_OPT_STRING, no_argument, &SMART_OFFLINE_SCAN_FLAG, goTrue } + #define LONG_DST_FLAG longDST #define LONG_DST_VAR getOptBool LONG_DST_FLAG = goFalse; #define LONG_DST_LONG_OPT_STRING "longDST" @@ -307,7 +337,7 @@ extern "C" bool SMART_ATTRIBUTES_FLAG = false; \ int SMART_ATTRIBUTES_MODE_FLAG = 0; #define SMART_ATTRIBUTES_LONG_OPT_STRING "smartAttributes" - #define SMART_ATTRIBUTES_LONG_OPT { SMART_ATTRIBUTES_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SMART_ATTRIBUTES_LONG_OPT { SMART_ATTRIBUTES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define NVME_HEALTH_FLAG showNVMeHealthData #define NVME_HEALTH_VAR getOptBool NVME_HEALTH_FLAG = goFalse; @@ -322,10 +352,10 @@ extern "C" #define IDD_TEST_FLAG iddOperation #define RUN_IDD_FLAG runIDDOp #define IDD_TEST_VARS \ - int IDD_TEST_FLAG = 0;\ - bool RUN_IDD_FLAG = false; + int IDD_TEST_FLAG = 0;\ + bool RUN_IDD_FLAG = false; #define IDD_TEST_LONG_OPT_STRING "idd" - #define IDD_TEST_LONG_OPT { IDD_TEST_LONG_OPT_STRING, required_argument, NULL, 0 } + #define IDD_TEST_LONG_OPT { IDD_TEST_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ABORT_IDD_FLAG abortIDD #define ABORT_IDD_VAR getOptBool ABORT_IDD_FLAG = goFalse; @@ -351,12 +381,12 @@ extern "C" #define OUTPUT_MODE_IDENTIFIER outputMode #define OUTPUT_MODE_VAR eOutputMode OUTPUT_MODE_IDENTIFIER = 0; #define OUTPUT_MODE_LONG_OPT_STRING "logMode" - #define OUTPUT_MODE_LONG_OPT { OUTPUT_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define OUTPUT_MODE_LONG_OPT { OUTPUT_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define EPC_ENABLED_IDENTIFIER enableEPC #define EPC_ENABLED_VAR eEPCFeatureSet EPC_ENABLED_IDENTIFIER = ENABLE_EPC_NOT_SET; #define EPC_ENABLED_LONG_OPT_STRING "EPCfeature" - #define EPC_ENABLED_LONG_OPT { EPC_ENABLED_LONG_OPT_STRING, required_argument, NULL, 0 } + #define EPC_ENABLED_LONG_OPT { EPC_ENABLED_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define POWER_STATE_ACTIVE_STRING "active" #define POWER_STATE_IDLE_STRING "idle" @@ -375,7 +405,7 @@ extern "C" bool TRANSITION_POWER_MODE_FLAG = false;\ int TRANSITION_POWER_MODE_TO_POWER_MODE = -1;/*-1 = not set*/ #define TRANSITION_POWER_MODE_LONG_OPT_STRING "transitionPower" - #define TRANSITION_POWER_MODE_LONG_OPT { TRANSITION_POWER_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TRANSITION_POWER_MODE_LONG_OPT { TRANSITION_POWER_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //New EPC Configuration settings to make things easier for changing multiple or individual settings at once with a simpler command line option #define POWER_MODE_STATE_ENABLE INT8_C(1) @@ -392,7 +422,7 @@ extern "C" uint32_t IDLE_A_POWER_MODE_TIMER = 0;\ int8_t IDLE_A_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define IDLE_A_LONG_OPT_STRING "idle_a" - #define IDLE_A_LONG_OPT { IDLE_A_LONG_OPT_STRING, required_argument, NULL, 0 } + #define IDLE_A_LONG_OPT { IDLE_A_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define IDLE_B_POWER_MODE_FLAG changeIdleBSettings #define IDLE_B_POWER_MODE_TIMER idleBTimerValue @@ -404,7 +434,7 @@ extern "C" uint32_t IDLE_B_POWER_MODE_TIMER = 0;\ int8_t IDLE_B_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define IDLE_B_LONG_OPT_STRING "idle_b" - #define IDLE_B_LONG_OPT { IDLE_B_LONG_OPT_STRING, required_argument, NULL, 0 } + #define IDLE_B_LONG_OPT { IDLE_B_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define IDLE_C_POWER_MODE_FLAG changeIdleCSettings #define IDLE_C_POWER_MODE_TIMER idleCTimerValue @@ -416,7 +446,7 @@ extern "C" uint32_t IDLE_C_POWER_MODE_TIMER = 0;\ int8_t IDLE_C_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define IDLE_C_LONG_OPT_STRING "idle_c" - #define IDLE_C_LONG_OPT { IDLE_C_LONG_OPT_STRING, required_argument, NULL, 0 } + #define IDLE_C_LONG_OPT { IDLE_C_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define STANDBY_Z_POWER_MODE_FLAG changeStandbyZSettings #define STANDBY_Z_POWER_MODE_TIMER standbyZTimerValue @@ -428,7 +458,7 @@ extern "C" uint32_t STANDBY_Z_POWER_MODE_TIMER = 0;\ int8_t STANDBY_Z_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define STANDBY_Z_LONG_OPT_STRING "standby_z" - #define STANDBY_Z_LONG_OPT { STANDBY_Z_LONG_OPT_STRING, required_argument, NULL, 0 } + #define STANDBY_Z_LONG_OPT { STANDBY_Z_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define STANDBY_Y_POWER_MODE_FLAG changeStandbyYSettings #define STANDBY_Y_POWER_MODE_TIMER standbyYTimerValue @@ -440,7 +470,7 @@ extern "C" uint32_t STANDBY_Y_POWER_MODE_TIMER = 0;\ int8_t STANDBY_Y_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define STANDBY_Y_LONG_OPT_STRING "standby_y" - #define STANDBY_Y_LONG_OPT { STANDBY_Y_LONG_OPT_STRING, required_argument, NULL, 0 } + #define STANDBY_Y_LONG_OPT { STANDBY_Y_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Legacy standby and idle (SAS only) timers #define LEGACY_IDLE_POWER_MODE_FLAG changeIdleSettings @@ -453,7 +483,7 @@ extern "C" uint32_t LEGACY_IDLE_POWER_MODE_TIMER = 0;\ int8_t LEGACY_IDLE_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define LEGACY_IDLE_LONG_OPT_STRING "idle" - #define LEGACY_IDLE_LONG_OPT { LEGACY_IDLE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define LEGACY_IDLE_LONG_OPT { LEGACY_IDLE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define LEGACY_STANDBY_POWER_MODE_FLAG changeStandbySettings #define LEGACY_STANDBY_POWER_MODE_TIMER standbyTimerValue @@ -465,7 +495,7 @@ extern "C" uint32_t LEGACY_STANDBY_POWER_MODE_TIMER = 0;\ int8_t LEGACY_STANDBY_STATE = POWER_MODE_STATE_ENABLE;/*assume enable unless given default or disable*/ #define LEGACY_STANDBY_LONG_OPT_STRING "standby" - #define LEGACY_STANDBY_LONG_OPT { LEGACY_STANDBY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define LEGACY_STANDBY_LONG_OPT { LEGACY_STANDBY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Add time delay between each IO #define DELAY_CMD_SEGMENT_FLAG delayIO @@ -474,13 +504,13 @@ extern "C" bool DELAY_CMD_SEGMENT_FLAG = false;\ uint32_t SET_CMD_TIME_DELAY = 0; #define DELAY_CMD_SEGMENT_LONG_OPT_STRING "delayCMDSegment" - #define DELAY_CMD_SEGMENT_LONG_OPT { DELAY_CMD_SEGMENT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define DELAY_CMD_SEGMENT_LONG_OPT { DELAY_CMD_SEGMENT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Following is for NVMe Utilities. #define TRANSITION_POWER_STATE_TO transitionPowerState #define TRANSITION_POWER_STATE_VAR int32_t TRANSITION_POWER_STATE_TO = -1; #define TRANSITION_POWER_STATE_LONG_OPT_STRING "transitionPowerState" - #define TRANSITION_POWER_STATE_LONG_OPT { TRANSITION_POWER_STATE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TRANSITION_POWER_STATE_LONG_OPT { TRANSITION_POWER_STATE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SHOW_NVM_POWER_STATES showNVMPowerStates #define SHOW_NVM_POWER_STATES_VAR getOptBool SHOW_NVM_POWER_STATES = goFalse; @@ -490,7 +520,7 @@ extern "C" #define GET_NVME_LOG_IDENTIFIER nvmeGetLogPage #define GET_NVME_LOG_VAR uint8_t GET_NVME_LOG_IDENTIFIER = 0; #define GET_NVME_LOG_LONG_OPT_STRING "getNvmeLogPage" - #define GET_NVME_LOG_LONG_OPT { GET_NVME_LOG_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GET_NVME_LOG_LONG_OPT { GET_NVME_LOG_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define CLEAR_PCIE_CORRECTABLE_ERRORS_LOG_FLAG clearpciecorrectableerrors #define CLEAR_PCIE_CORRECTABLE_ERRORS_LOG_VAR getOptBool CLEAR_PCIE_CORRECTABLE_ERRORS_LOG_FLAG = goFalse; @@ -503,7 +533,7 @@ extern "C" uint16_t GET_FEATURES = UINT16_MAX;\ bool GET_FEATURES_FLAG = false; #define GET_FEATURES_LONG_OPT_STRING "getFeatures" - #define GET_FEATURES_LONG_OPT { GET_FEATURES_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GET_FEATURES_LONG_OPT { GET_FEATURES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } // NVMe Temperature Statistics #define NVME_TEMP_STATS_FLAG nvmeTempStats @@ -521,13 +551,13 @@ extern "C" #define GET_TELEMETRY_IDENTIFIER getTelemetryData #define GET_TELEMETRY_VAR uint8_t GET_TELEMETRY_IDENTIFIER = 0; #define GET_TELEMETRY_LONG_OPT_STRING "getTelemetry" /* host | cntl | current | saved */ - #define GET_TELEMETRY_LONG_OPT { GET_TELEMETRY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GET_TELEMETRY_LONG_OPT { GET_TELEMETRY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Telemetry Data Area #define TELEMETRY_DATA_AREA telemetryDataArea #define TELEMETRY_DATA_AREA_VAR uint8_t TELEMETRY_DATA_AREA = 3; #define TELEMETRY_DATA_AREA_LONG_OPT_STRING "telemetryDataArea" - #define TELEMETRY_DATA_AREA_LONG_OPT { TELEMETRY_DATA_AREA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TELEMETRY_DATA_AREA_LONG_OPT { TELEMETRY_DATA_AREA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ZERO_VERIFY_FLAG runZeroVerify #define ZERO_VERIFY_MODE_FLAG runZeroVerifyMode @@ -535,7 +565,7 @@ extern "C" bool ZERO_VERIFY_FLAG = false; \ int ZERO_VERIFY_MODE_FLAG = 0; /*0 = full, 1 = quick*/ #define ZERO_VERIFY_LONG_OPT_STRING "zeroVerify" - #define ZERO_VERIFY_LONG_OPT { ZERO_VERIFY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ZERO_VERIFY_LONG_OPT { ZERO_VERIFY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //before erasing a drive, restore the max LBA to make sure all user accessible spaces will be erased. #define ERASE_RESTORE_MAX_PREP eraseRestoreMaxLBAPrep @@ -547,7 +577,7 @@ extern "C" #define GENERIC_TEST_MODE_FLAG genericTestMode #define GENERIC_TEST_MODE_VAR int genericTestMode = 0; //0 = read, 1 = write, 2 = verify #define GENERIC_TEST_LONG_OPT_STRING "genericMode" - #define GENERIC_TEST_LONG_OPT { GENERIC_TEST_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GENERIC_TEST_LONG_OPT { GENERIC_TEST_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //buffer test #define BUFFER_TEST_FLAG performBufferTest @@ -580,7 +610,7 @@ extern "C" #define RUN_USER_GENERIC_TEST_VAR \ bool RUN_USER_GENERIC_TEST = false; #define USER_GENERIC_LONG_OPT_START_STRING "userGenericStart" - #define USER_GENERIC_START_LONG_OPT { USER_GENERIC_LONG_OPT_START_STRING, required_argument, NULL, 0 } + #define USER_GENERIC_START_LONG_OPT { USER_GENERIC_LONG_OPT_START_STRING, required_argument, M_NULLPTR, 0 } #define USER_GENERIC_RANGE_UNITS_SPECIFIED userGenericRangeUsingUnits #define USER_GENERIC_RANGE_FLAG userGenericRange @@ -588,7 +618,7 @@ extern "C" uint64_t USER_GENERIC_RANGE_FLAG = 0;\ bool USER_GENERIC_RANGE_UNITS_SPECIFIED = false; #define USER_GENERIC_LONG_OPT_RANGE_STRING "userGenericRange" - #define USER_GENERIC_RANGE_LONG_OPT { USER_GENERIC_LONG_OPT_RANGE_STRING, required_argument, NULL, 0 } + #define USER_GENERIC_RANGE_LONG_OPT { USER_GENERIC_LONG_OPT_RANGE_STRING, required_argument, M_NULLPTR, 0 } #define ERROR_LIMIT_FLAG errorLimit #define ERROR_LIMIT_LOGICAL_COUNT errorLimitIsInLogicalBlocks @@ -596,7 +626,7 @@ extern "C" uint16_t ERROR_LIMIT_FLAG = 50;/*default value unless 512/4k which will be 400*/\ bool ERROR_LIMIT_LOGICAL_COUNT = false;//default to being in physical blocks #define ERROR_LIMIT_LONG_OPT_STRING "errorLimit" - #define ERROR_LIMIT_LONG_OPT { ERROR_LIMIT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ERROR_LIMIT_LONG_OPT { ERROR_LIMIT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define RANDOM_READ_TEST_FLAG randomReadTest #define RANDOM_READ_TEST_VAR \ @@ -634,19 +664,19 @@ extern "C" #define HOURS_TIME_VAR \ uint8_t HOURS_TIME_FLAG = 0; #define HOURS_TIME_LONG_OPT_STRING "hours" - #define HOURS_TIME_LONG_OPT { HOURS_TIME_LONG_OPT_STRING, required_argument, NULL, 0 } + #define HOURS_TIME_LONG_OPT { HOURS_TIME_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define MINUTES_TIME_FLAG timeMinutes #define MINUTES_TIME_VAR \ uint16_t MINUTES_TIME_FLAG = 0; #define MINUTES_TIME_LONG_OPT_STRING "minutes" - #define MINUTES_TIME_LONG_OPT { MINUTES_TIME_LONG_OPT_STRING, required_argument, NULL , 0 } + #define MINUTES_TIME_LONG_OPT { MINUTES_TIME_LONG_OPT_STRING, required_argument, M_NULLPTR , 0 } #define SECONDS_TIME_FLAG timeSeconds #define SECONDS_TIME_VAR \ uint32_t SECONDS_TIME_FLAG = 0; #define SECONDS_TIME_LONG_OPT_STRING "seconds" - #define SECONDS_TIME_LONG_OPT { SECONDS_TIME_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SECONDS_TIME_LONG_OPT { SECONDS_TIME_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //overwrite flags (overwrite for a time will be handled with the above time flags) #define OVERWRITE_START_FLAG overwriteStart @@ -657,9 +687,9 @@ extern "C" uint64_t OVERWRITE_RANGE_FLAG = 0; \ bool RUN_OVERWRITE_FLAG = false; #define OVERWRITE_LONG_OPT_STRING "overwrite" - #define OVERWRITE_LONG_OPT { OVERWRITE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define OVERWRITE_LONG_OPT { OVERWRITE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define OVERWRITE_RANGE_LONG_OPT_STRING "overwriteRange" - #define OVERWRITE_RANGE_LONG_OPT { OVERWRITE_RANGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define OVERWRITE_RANGE_LONG_OPT { OVERWRITE_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define OVERWRITE_LONG_OPTS OVERWRITE_LONG_OPT,OVERWRITE_RANGE_LONG_OPT //trim/unmap flags @@ -672,12 +702,12 @@ extern "C" bool RUN_TRIM_UNMAP_FLAG = false; #define TRIM_LONG_OPT_STRING "trim" #define UNMAP_LONG_OPT_STRING "unmap" - #define TRIM_LONG_OPT { TRIM_LONG_OPT_STRING, required_argument, NULL, 0 } - #define UNMAP_LONG_OPT { UNMAP_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TRIM_LONG_OPT { TRIM_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define UNMAP_LONG_OPT { UNMAP_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define TRIM_RANGE_LONG_OPT_STRING "trimRange" - #define TRIM_RANGE_LONG_OPT { TRIM_RANGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TRIM_RANGE_LONG_OPT { TRIM_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define UNMAP_RANGE_LONG_OPT_STRING "unmapRange" - #define UNMAP_RANGE_LONG_OPT { UNMAP_RANGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define UNMAP_RANGE_LONG_OPT { UNMAP_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define TRIM_LONG_OPTS TRIM_LONG_OPT,TRIM_RANGE_LONG_OPT #define UNMAP_LONG_OPTS UNMAP_LONG_OPT,UNMAP_RANGE_LONG_OPT @@ -690,28 +720,28 @@ extern "C" uint64_t WRITE_SAME_RANGE_FLAG = 0;\ bool RUN_WRITE_SAME_FLAG = false; #define WRITE_SAME_LONG_OPT_STRING "writeSame" - #define WRITE_SAME_LONG_OPT { WRITE_SAME_LONG_OPT_STRING, required_argument, NULL, 0 } + #define WRITE_SAME_LONG_OPT { WRITE_SAME_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define WRITE_SAME_RANGE_LONG_OPT_STRING "writeSameRange" - #define WRITE_SAME_RANGE_LONG_OPT { WRITE_SAME_RANGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define WRITE_SAME_RANGE_LONG_OPT { WRITE_SAME_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define WRITE_SAME_LONG_OPTS WRITE_SAME_LONG_OPT,WRITE_SAME_RANGE_LONG_OPT //TCG SID flag #define TCG_SID_BUF_LEN 33 #define TCG_SID_FLAG sid #define TCG_SID_VARS \ - char sidBuf[TCG_SID_BUF_LEN] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, sidBuf, TCG_SID_BUF_LEN);\ char* TCG_SID_FLAG = &sidBuf[0]; #define TCG_SID_LONG_OPT_STRING "sid" - #define TCG_SID_LONG_OPT { TCG_SID_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TCG_SID_LONG_OPT { TCG_SID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //TCG PSID flag #define TCG_PSID_BUF_LEN 33 #define TCG_PSID_FLAG psid #define TCG_PSID_VARS \ - char psidBuf[TCG_PSID_BUF_LEN] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, psidBuf, TCG_PSID_BUF_LEN);\ char* TCG_PSID_FLAG = &psidBuf[0]; #define TCG_PSID_LONG_OPT_STRING "psid" - #define TCG_PSID_LONG_OPT { TCG_PSID_LONG_OPT_STRING, required_argument, NULL, 0 } + #define TCG_PSID_LONG_OPT { TCG_PSID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //revertSP flags #define TCG_REVERT_SP_FLAG revertSP @@ -746,35 +776,92 @@ extern "C" uint8_t SET_POWER_CONSUMPTION_ACTIVE_LEVEL_VALUE = 0;\ double SET_POWER_CONSUMPTION_WATTS_VALUE = 0; #define SET_POWER_CONSUMPTION_LONG_OPT_STRING "setPowerConsumption" - #define SET_POWER_CONSUMPTION_LONG_OPT { SET_POWER_CONSUMPTION_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_POWER_CONSUMPTION_LONG_OPT { SET_POWER_CONSUMPTION_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //SATA Only Sanitize freeze/antifreeze lock variables. These can be used to block sanitize, or stop a system from blocking sanitize with a freezelock + #define SANITIZE_FREEZE sanitizeFreezeLock + #define SANITIZE_FREEZE_VAR getOptBool SANITIZE_FREEZE = goFalse; + #define SANITIZE_FREEZE_LONG_OPT_STRING "sanitizeFreeze" + #define SANITIZE_FREEZE_LONG_OPT { SANITIZE_FREEZE_LONG_OPT_STRING, no_argument, &SANITIZE_FREEZE, goTrue } + + #define SANITIZE_ANTIFREEZE sanitizeAntiFreezeLock + #define SANITIZE_ANTIFREEZE_VAR getOptBool SANITIZE_ANTIFREEZE = goFalse; + #define SANITIZE_ANTIFREEZE_LONG_OPT_STRING "sanitizeAntiFreeze" + #define SANITIZE_ANTIFREEZE_LONG_OPT { SANITIZE_ANTIFREEZE_LONG_OPT_STRING, no_argument, &SANITIZE_ANTIFREEZE, goTrue } - //sanitize TODO: This is incomplete. Need to expand this a bit more and then clean up the implementation for command line parsing in openSeaChest_Erase + + #define SANITIZE_BLOCK_ERASE_STR "blockerase" + #define SANITIZE_CRYPTO_ERASE_STR "cryptoerase" + #define SANITIZE_OVERWRITE_ERASE_STR "overwrite" + + #define SANITIZE_INFO_FLAG sanitizeCapabilities + #define SANITIZE_RUN_BLOCK_ERASE sanitizeBlockErase + #define SANITIZE_RUN_CRYPTO_ERASE sanitizeCryptoErase + #define SANITIZE_RUN_OVERWRITE_ERASE sanitizeOverwriteErase #define SANITIZE_RUN_FLAG sanitize #define SANITIZE_UTIL_VARS \ bool SANITIZE_RUN_FLAG = false; \ - bool sanitizeInfo = false; \ - bool sanblockErase = false; \ - bool sancryptoErase = false; \ - bool sanoverwrite = false; \ - bool sanfreezelock = false; \ - bool sanAntiFreezeLock = false; + bool SANITIZE_INFO_FLAG = false; \ + bool SANITIZE_RUN_BLOCK_ERASE = false; \ + bool SANITIZE_RUN_CRYPTO_ERASE = false; \ + bool SANITIZE_RUN_OVERWRITE_ERASE = false; #define SANITIZE_LONG_OPT_STRING "sanitize" + #define SANITIZE_LONG_OPT { SANITIZE_LONG_OPT_STRING, required_argument, M_NULLPTR, 'e' } + + //allow unrestricted sanitize exit option + #define SANITIZE_AUSE sanitizeAUSE + #define SANITIZE_AUSE_VAR getOptBool SANITIZE_AUSE = goFalse; + #define SANITIZE_AUSE_LONG_OPT_STRING "ause" + #define SANITIZE_AUSE_LONG_OPT { SANITIZE_AUSE_LONG_OPT_STRING, no_argument, &SANITIZE_AUSE, goTrue } + + //Sanitize overwrite invert pattern flag (invert between overwrite passes) + #define SANITIZE_IPBP sanitizeIPBP + #define SANITIZE_IPBP_VAR getOptBool SANITIZE_IPBP = goFalse; + #define SANITIZE_IPBP_LONG_OPT_STRING "ipbp" + #define SANITIZE_IPBP_LONG_OPT { SANITIZE_IPBP_LONG_OPT_STRING, no_argument, &SANITIZE_IPBP, goTrue } + + //Sanitize overwrite number of overwrite passes flag + #define SANITIZE_OVERWRITE_PASSES sanitizeOverwritePasses + #define SANITIZE_OVERWRITE_PASSES_VAR uint8_t SANITIZE_OVERWRITE_PASSES = 1;//default to a single pass. Max number depends on the drive standard implemented. (ATA/NVMe = 16, SCSI = 31) + #define SANITIZE_OVERWRITE_PASSES_LONG_OPT_STRING "overwritepasses" + #define SANITIZE_OVERWRITE_PASSES_LONG_OPT { SANITIZE_OVERWRITE_PASSES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //zone no reset bit. Can be used in Sanitize erases or ATA security erase. + //when set, zones are left full to allow for verification. When not set, all write pointers are reset to the beginning of the zones. + #define ZONE_NO_RESET zbdZoneNoReset + #define ZONE_NO_RESET_VAR getOptBool ZONE_NO_RESET = goFalse; + #define ZONE_NO_RESET_LONG_OPT_STRING "znr" + #define ZONE_NO_RESET_LONG_OPT { ZONE_NO_RESET_LONG_OPT_STRING, no_argument, &ZONE_NO_RESET, goTrue } + + //No deallocate (NVMe for Sanitize command)...not currently in SATA or SAS, but maybe it will be one day-TJE + //when set, and the controller is not inhibiting this behavior, it allows reading and verifying all LBAs were erased. + #define NO_DEALLOCATE_AFTER_ERASE nvmeNoDeallocate + #define NO_DEALLOCATE_AFTER_ERASE_VAR getOptBool NO_DEALLOCATE_AFTER_ERASE = goFalse; + #define NO_DEALLOCATE_AFTER_ERASE_LONG_OPT_STRING "nodeallocate" + #define NO_DEALLOCATE_AFTER_ERASE_LONG_OPT { NO_DEALLOCATE_AFTER_ERASE_LONG_OPT_STRING, no_argument, &NO_DEALLOCATE_AFTER_ERASE, goTrue } + + //Call the function to refresh the known filesystems in the OS. This can be very important to do after an erase is completed. + //If an erase is completed this is done automatically already, however if polling for progress or needing a write after erase (SAS crypto/block) + //then a user may need to call this another time as well manually. + #define REFRESH_FILE_SYSTEMS refreshFileSystems + #define REFRESH_FILE_SYSTEMS_VAR getOptBool REFRESH_FILE_SYSTEMS = goFalse; + #define REFRESH_FILE_SYSTEMS_LONG_OPT_STRING "refreshfs" + #define REFRESH_FILE_SYSTEMS_LONG_OPT { REFRESH_FILE_SYSTEMS_LONG_OPT_STRING, no_argument, &REFRESH_FILE_SYSTEMS, goTrue } //download FW #define FIRMWARE_FILE_NAME_MAX_LEN 4096 - #define FIRMWARE_FILE_NAME_MAX_LEN_FORMAT_STR "%4096s" #define DOWNLOAD_FW_FLAG downloadFW #define DOWNLOAD_FW_FILENAME_FLAG downloadFWFilename #define DOWNLOAD_FW_MODE downloadMode #define DOWNLOAD_FW_VARS \ bool DOWNLOAD_FW_FLAG = false;\ - char firmwareFileName[FIRMWARE_FILE_NAME_MAX_LEN] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, firmwareFileName, FIRMWARE_FILE_NAME_MAX_LEN);\ char *DOWNLOAD_FW_FILENAME_FLAG = &firmwareFileName[0];\ int DOWNLOAD_FW_MODE = 0xFF;/*automatic*/ #define DOWNLOAD_FW_LONG_OPT_STRING "downloadFW" #define DOWNLOAD_FW_MODE_LONG_OPT_STRING "downloadMode" - #define DOWNLOAD_FW_LONG_OPT { DOWNLOAD_FW_LONG_OPT_STRING, required_argument, NULL, 0 } - #define DOWNLOAD_FW_MODE_LONG_OPT { DOWNLOAD_FW_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define DOWNLOAD_FW_LONG_OPT { DOWNLOAD_FW_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define DOWNLOAD_FW_MODE_LONG_OPT { DOWNLOAD_FW_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //activate deferred FW #define ACTIVATE_DEFERRED_FW_FLAG activateDeferredFW @@ -792,7 +879,7 @@ extern "C" #define FORCE_NVME_COMMIT_ACTION forceCommitAction #define FORCE_NVME_COMMIT_ACTION_VAR uint8_t FORCE_NVME_COMMIT_ACTION = 0xFF;//something not possible to be valid #define FORCE_NVME_COMMIT_ACTION_LONG_OPT_STRING "forceNVMeCA" - #define FORCE_NVME_COMMIT_ACTION_LONG_OPT { FORCE_NVME_COMMIT_ACTION_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FORCE_NVME_COMMIT_ACTION_LONG_OPT { FORCE_NVME_COMMIT_ACTION_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //nvme unique flag to disable issuing a reset after a firmware commit #define FORCE_DISABLE_NVME_FW_COMMIT_RESET forceDisableNVMeFWReset @@ -817,8 +904,8 @@ extern "C" #define FIRMWARE_SLOT_VAR uint8_t FIRMWARE_SLOT_FLAG = 0;//default to zero should be ok #define FIRMWARE_SLOT_LONG_OPT_STRING "firmwareSlot" #define FIRMWARE_BUFFER_ID_LONG_OPT_STRING "fwBufferID" - #define FIRMWARE_SLOT_LONG_OPT { FIRMWARE_SLOT_LONG_OPT_STRING, required_argument, NULL, 0 } - #define FIRMWARE_BUFFER_ID_LONG_OPT { FIRMWARE_BUFFER_ID_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FIRMWARE_SLOT_LONG_OPT { FIRMWARE_SLOT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define FIRMWARE_BUFFER_ID_LONG_OPT { FIRMWARE_BUFFER_ID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define FIRMWARE_SLOT_BUFFER_ID_LONG_OPT FIRMWARE_SLOT_LONG_OPT,FIRMWARE_BUFFER_ID_LONG_OPT //model number match @@ -827,10 +914,10 @@ extern "C" #define MODEL_STRING_LENGTH 41 #define MODEL_MATCH_VARS \ bool MODEL_MATCH_FLAG = false;\ - char modelMatchArray[MODEL_STRING_LENGTH] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, modelMatchArray, MODEL_STRING_LENGTH);\ char *MODEL_STRING_FLAG = &modelMatchArray[0]; #define MODEL_MATCH_LONG_OPT_STRING "modelMatch" - #define MODEL_MATCH_LONG_OPT { MODEL_MATCH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define MODEL_MATCH_LONG_OPT { MODEL_MATCH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //fw rev match #define FW_MATCH_FLAG fwNumberMatch @@ -838,10 +925,10 @@ extern "C" #define FW_STRING_FLAG fwString #define FW_MATCH_VARS \ bool FW_MATCH_FLAG = false;\ - char fwMatchArray[FW_MATCH_STRING_LENGTH] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, fwMatchArray, FW_MATCH_STRING_LENGTH);\ char *FW_STRING_FLAG = &fwMatchArray[0]; #define FW_MATCH_LONG_OPT_STRING "onlyFW" - #define FW_MATCH_LONG_OPT { FW_MATCH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FW_MATCH_LONG_OPT { FW_MATCH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //new fw rev match #define NEW_FW_MATCH_STRING_LENGTH 9 @@ -849,10 +936,10 @@ extern "C" #define NEW_FW_STRING_FLAG newfwString #define NEW_FW_MATCH_VARS \ bool NEW_FW_MATCH_FLAG = false;\ - char newfwMatchArray[NEW_FW_MATCH_STRING_LENGTH] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, newfwMatchArray, NEW_FW_MATCH_STRING_LENGTH);\ char *NEW_FW_STRING_FLAG = &newfwMatchArray[0]; #define NEW_FW_MATCH_LONG_OPT_STRING "newFW" - #define NEW_FW_MATCH_LONG_OPT { NEW_FW_MATCH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define NEW_FW_MATCH_LONG_OPT { NEW_FW_MATCH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //child model number match #define CHILD_MODEL_MATCH_FLAG childModelNumberMatch @@ -860,10 +947,10 @@ extern "C" #define CHILD_MATCH_STRING_LENGTH 41 #define CHILD_MODEL_MATCH_VARS \ bool CHILD_MODEL_MATCH_FLAG = false;\ - char childModelMatchArray[CHILD_MATCH_STRING_LENGTH] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, childModelMatchArray, CHILD_MATCH_STRING_LENGTH);\ char *CHILD_MODEL_STRING_FLAG = &childModelMatchArray[0]; #define CHILD_MODEL_MATCH_LONG_OPT_STRING "childModelMatch" - #define CHILD_MODEL_MATCH_LONG_OPT { CHILD_MODEL_MATCH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define CHILD_MODEL_MATCH_LONG_OPT { CHILD_MODEL_MATCH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //child fw rev match #define CHILD_FW_MATCH_FLAG childFwNumberMatch @@ -871,10 +958,10 @@ extern "C" #define CHILD_FW_MATCH_STRING_LENGTH 9 #define CHILD_FW_MATCH_VARS \ bool CHILD_FW_MATCH_FLAG = false;\ - char childFwMatchArray[CHILD_FW_MATCH_STRING_LENGTH] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, childFwMatchArray, CHILD_FW_MATCH_STRING_LENGTH);\ char *CHILD_FW_STRING_FLAG = &childFwMatchArray[0]; #define CHILD_FW_MATCH_LONG_OPT_STRING "childOnlyFW" - #define CHILD_FW_MATCH_LONG_OPT { CHILD_FW_MATCH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define CHILD_FW_MATCH_LONG_OPT { CHILD_FW_MATCH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //child new fw rev match #define CHILD_NEW_FW_STRING_MATCH_LENGTH 9 @@ -882,10 +969,10 @@ extern "C" #define CHILD_NEW_FW_STRING_FLAG childNewfwString #define CHILD_NEW_FW_MATCH_VARS \ bool CHILD_NEW_FW_MATCH_FLAG = false;\ - char childNewfwMatchArray[CHILD_NEW_FW_STRING_MATCH_LENGTH] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, childNewfwMatchArray, CHILD_NEW_FW_STRING_MATCH_LENGTH);\ char *CHILD_NEW_FW_STRING_FLAG = &childNewfwMatchArray[0]; #define CHILD_NEW_FW_MATCH_LONG_OPT_STRING "childNewFW" - #define CHILD_NEW_FW_MATCH_LONG_OPT { CHILD_NEW_FW_MATCH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define CHILD_NEW_FW_MATCH_LONG_OPT { CHILD_NEW_FW_MATCH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //setmaxlba #define SET_MAX_LBA_FLAG setMaxLBA @@ -894,7 +981,7 @@ extern "C" bool SET_MAX_LBA_FLAG = false;\ uint64_t SET_MAX_LBA_VALUE = UINT64_MAX; #define SET_MAX_LBA_LONG_OPT_STRING "setMaxLBA" - #define SET_MAX_LBA_LONG_OPT { SET_MAX_LBA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_MAX_LBA_LONG_OPT { SET_MAX_LBA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //restore maxlba #define RESTORE_MAX_LBA_FLAG restoreMaxLBA @@ -906,7 +993,7 @@ extern "C" #define PROVISION_FLAG provisionDrive #define PROVISION_VAR bool provisionDrive = false; #define PROVISION_LONG_OPT_STRING "provision" - #define PROVISION_LONG_OPT { PROVISION_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PROVISION_LONG_OPT { PROVISION_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //set phy speed #define SET_PHY_ALL_PHYS setAllPhys @@ -917,13 +1004,13 @@ extern "C" uint8_t SET_PHY_SPEED_GEN = 0;\ bool SET_PHY_ALL_PHYS = true;//this will be changed to false when a specific phy is selected for SAS #define SET_PHY_SPEED_LONG_OPT_STRING "phySpeed" - #define SET_PHY_SPEED_LONG_OPT { SET_PHY_SPEED_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_PHY_SPEED_LONG_OPT { SET_PHY_SPEED_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //--sasPhy....to be used with various other SAS operations that need an identifier. #define SET_PHY_SAS_PHY_IDENTIFIER sasPhyIdentifier #define SET_PHY_SAS_PHY_IDENTIFIER_VAR uint8_t SET_PHY_SAS_PHY_IDENTIFIER = 0xFF; #define SET_PHY_SAS_PHY_LONG_OPT_STRING "sasPhy" - #define SET_PHY_SAS_PHY_LONG_OPT { SET_PHY_SAS_PHY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_PHY_SAS_PHY_LONG_OPT { SET_PHY_SAS_PHY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //sas phy link test patterns options...STD spec, but a couple options may be Seagate only. #define SAS_PHY_TEST_PATTERN testPattern @@ -948,15 +1035,15 @@ extern "C" #define SAS_PHY_STOP_TEST_PATTERN_LONG_OPT_STRING "sasStopPhyTestPattern" #define SAS_PHY_STOP_TEST_PATTERN_LONG_OPT { SAS_PHY_STOP_TEST_PATTERN_LONG_OPT_STRING, no_argument, &SAS_PHY_STOP_TEST_PATTERN_FLAG, goTrue } #define SAS_PHY_TEST_PATTERN_LONG_OPT_STRING "sasPhyTestPattern" - #define SAS_PHY_TEST_PATTERN_LONG_OPT { SAS_PHY_TEST_PATTERN_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_PHY_TEST_PATTERN_LONG_OPT { SAS_PHY_TEST_PATTERN_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SAS_PHY_TEST_FUNCTION_SSC_LONG_OPT_STRING "sasPhySSC" - #define SAS_PHY_TEST_FUNCTION_SSC_LONG_OPT { SAS_PHY_TEST_FUNCTION_SSC_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_PHY_TEST_FUNCTION_SSC_LONG_OPT { SAS_PHY_TEST_FUNCTION_SSC_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SAS_PHY_LINK_RATE_LONG_OPT_STRING "sasPhyTestLinkRate" - #define SAS_PHY_LINK_RATE_LONG_OPT { SAS_PHY_LINK_RATE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_PHY_LINK_RATE_LONG_OPT { SAS_PHY_LINK_RATE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SAS_PHY_DWORD_CONTROL_LONG_OPT_STRING "sasPhyDWordControl" - #define SAS_PHY_DWORD_CONTROL_LONG_OPT { SAS_PHY_DWORD_CONTROL_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_PHY_DWORD_CONTROL_LONG_OPT { SAS_PHY_DWORD_CONTROL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SAS_PHY_DWORDS_LONG_OPT_STRING "sasPhyDwordPattern" - #define SAS_PHY_DWORDS_LONG_OPT { SAS_PHY_DWORDS_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_PHY_DWORDS_LONG_OPT { SAS_PHY_DWORDS_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //set/get SSC #define SET_SSC_FLAG setSSC @@ -967,7 +1054,7 @@ extern "C" bool GET_SSC_FLAG = false;\ int SSC_MODE = 0; #define SSC_FEATURE_LONG_OPT_STRING "sscFeature" - #define SSC_FEATURE_LONG_OPT { SSC_FEATURE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SSC_FEATURE_LONG_OPT { SSC_FEATURE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //set ready LED - previously misnamed pin11 @@ -981,9 +1068,9 @@ extern "C" bool SET_READY_LED_DEFAULT = false;\ bool READY_LED_INFO_FLAG = false; #define SET_PIN_11_LONG_OPT_STRING "pin11" //left for backwards compatibility - #define SET_PIN_11_LONG_OPT { SET_PIN_11_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_PIN_11_LONG_OPT { SET_PIN_11_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SET_READY_LED_LONG_OPT_STRING "readyLED" //left for backwards compatibility - #define SET_READY_LED_LONG_OPT { SET_READY_LED_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_READY_LED_LONG_OPT { SET_READY_LED_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SET_READY_LED_LONG_OPTS SET_PIN_11_LONG_OPT, SET_READY_LED_LONG_OPT //Non-volatile cache (SCSI only) @@ -995,7 +1082,7 @@ extern "C" bool NV_CACHE_SETTING = false;\ bool NV_CACHE_FLAG = false; #define NV_CACHE_LONG_OPT_STRING "nvCache" - #define NV_CACHE_LONG_OPT { NV_CACHE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define NV_CACHE_LONG_OPT { NV_CACHE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //read look ahead #define READ_LOOK_AHEAD_INFO readLookAheadInfo @@ -1006,7 +1093,7 @@ extern "C" bool READ_LOOK_AHEAD_SETTING = false;\ bool READ_LOOK_AHEAD_FLAG = false; #define READ_LOOK_AHEAD_LONG_OPT_STRING "readLookAhead" - #define READ_LOOK_AHEAD_LONG_OPT { READ_LOOK_AHEAD_LONG_OPT_STRING, required_argument, NULL, 0 } + #define READ_LOOK_AHEAD_LONG_OPT { READ_LOOK_AHEAD_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //write cache #define WRITE_CACHE_INFO writeCacheInfo @@ -1017,7 +1104,7 @@ extern "C" bool WRITE_CACHE_SETTING = false;\ bool WRITE_CACHE_FLAG = false; #define WRITE_CACHE_LONG_OPT_STRING "writeCache" - #define WRITE_CACHE_LONG_OPT { WRITE_CACHE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define WRITE_CACHE_LONG_OPT { WRITE_CACHE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //sct write cache (enable/disable/default) #define SCT_WRITE_CACHE_INFO sctwriteCacheInfo @@ -1030,7 +1117,7 @@ extern "C" bool SCT_WRITE_CACHE_FLAG = false;\ bool SCT_WRITE_CACHE_SET_DEFAULT = false; #define SCT_WRITE_CACHE_LONG_OPT_STRING "sctWriteCache" - #define SCT_WRITE_CACHE_LONG_OPT { SCT_WRITE_CACHE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCT_WRITE_CACHE_LONG_OPT { SCT_WRITE_CACHE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //sct write cache reordering #define SCT_WRITE_CACHE_REORDER_INFO sctwriteCacheReorderInfo @@ -1043,7 +1130,7 @@ extern "C" bool SCT_WRITE_CACHE_REORDER_FLAG = false;\ bool SCT_WRITE_CACHE_REORDER_SET_DEFAULT = false; #define SCT_WRITE_CACHE_REORDER_LONG_OPT_STRING "sctWriteCacheReordering" - #define SCT_WRITE_CACHE_REORDER_LONG_OPT { SCT_WRITE_CACHE_REORDER_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCT_WRITE_CACHE_REORDER_LONG_OPT { SCT_WRITE_CACHE_REORDER_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //sct error recovery control #define SCT_ERROR_RECOVERY_CONTROL_READ_INFO showSCTErrorRecoveryReadInfo @@ -1069,8 +1156,8 @@ extern "C" SCT_ERROR_RECOVERY_CONTROL_WRITE_VARS #define SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING "sctReadTimer" #define SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT_STRING "sctWriteTimer" - #define SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT { SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING, required_argument, NULL, 0 } - #define SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT { SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT { SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT { SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SCT_ERROR_RECOVERY_CONTROL_LONG_OPTS SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT,SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT //volatile @@ -1098,7 +1185,7 @@ extern "C" bool FORMAT_UNIT_FLAG = false; \ uint16_t FORMAT_SECTOR_SIZE = 0; #define FORMAT_UNIT_LONG_OPT_STRING "formatUnit" - #define FORMAT_UNIT_LONG_OPT { FORMAT_UNIT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FORMAT_UNIT_LONG_OPT { FORMAT_UNIT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //other format unit options #define FORMAT_UNIT_DISABLE_PRIMARY_LIST_FLAG disablePrimaryList @@ -1143,12 +1230,12 @@ extern "C" #define FORMAT_UNIT_DISCARD_GROWN_DEFECT_LIST_FLAG_LONG_OPT { FORMAT_UNIT_DISCARD_GROWN_DEFECT_LIST_FLAG_LONG_OPT_STRING, no_argument, &FORMAT_UNIT_DISCARD_GROWN_DEFECT_LIST_FLAG, goTrue } #define FORMAT_UNIT_DISABLE_CERTIFICATION_LONG_OPT { FORMAT_UNIT_DISABLE_CERTIFICATION_LONG_OPT_STRING, no_argument, &FORMAT_UNIT_DISABLE_CERTIFICATION, goTrue } #define FORMAT_UNIT_SECURITY_INITIALIZE_LONG_OPT { FORMAT_UNIT_SECURITY_INITIALIZE_LONG_OPT_STRING, no_argument, &FORMAT_UNIT_SECURITY_INITIALIZE, goTrue } - #define FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT { FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT_STRING, required_argument, NULL, 0 } - #define FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT { FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT { FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT { FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define FORMAT_UNIT_DEFAULT_FORMAT_LONG_OPT { FORMAT_UNIT_DEFAULT_FORMAT_LONG_OPT_STRING, no_argument, &FORMAT_UNIT_DEFAULT_FORMAT, goTrue } #define FORMAT_UNIT_DISABLE_IMMEDIATE_RESPONSE_LONG_OPT { FORMAT_UNIT_DISABLE_IMMEDIATE_RESPONSE_LONG_OPT_STRING, no_argument, &FORMAT_UNIT_DISABLE_IMMEDIATE_RESPONSE, goTrue } #define FORMAT_UNIT_STOP_ON_LIST_ERROR_LONG_OPT { FORMAT_UNIT_STOP_ON_LIST_ERROR_LONG_OPT_STRING, no_argument, &FORMAT_UNIT_STOP_ON_LIST_ERROR, goTrue } - #define FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT { FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT { FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define FORMAT_UNIT_ADDITIONAL_OPTIONS\ FORMAT_UNIT_DISABLE_PRIMARY_LIST_FLAG_LONG_OPT,FORMAT_UNIT_DISCARD_GROWN_DEFECT_LIST_FLAG_LONG_OPT,FORMAT_UNIT_DISABLE_CERTIFICATION_LONG_OPT,FORMAT_UNIT_SECURITY_INITIALIZE_LONG_OPT,\ FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT,FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT,FORMAT_UNIT_DEFAULT_FORMAT_LONG_OPT,FORMAT_UNIT_DISABLE_IMMEDIATE_RESPONSE_LONG_OPT,FORMAT_UNIT_STOP_ON_LIST_ERROR_LONG_OPT,FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT @@ -1160,7 +1247,7 @@ extern "C" bool NVM_FORMAT_FLAG = false;\ uint32_t NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM = 16;/*leave this at 16 since it's neither a valid sector size or a valid format to format the drive with.*/ #define NVM_FORMAT_LONG_OPT_STRING "nvmFormat" - #define NVM_FORMAT_LONG_OPT { NVM_FORMAT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define NVM_FORMAT_LONG_OPT { NVM_FORMAT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Additional flags for nvmeFormat #define NVM_FORMAT_NSID nvmFormatNSID //default to all F's @@ -1185,14 +1272,14 @@ extern "C" #define NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING "nvmFmtMS" //value in bytes for metadata size #define NVM_FORMAT_METADATA_SETTING_LONG_OPT_STRING "nvmFmtMetadataSet" //[xlba | separate] - #define NVM_FORMAT_NSID_LONG_OPT { NVM_FORMAT_NSID_LONG_OPT_STRING, required_argument, NULL, 0 } - #define NVM_FORMAT_SECURE_ERASE_LONG_OPT { NVM_FORMAT_SECURE_ERASE_LONG_OPT_STRING, required_argument, NULL, 0 } - #define NVM_FORMAT_PI_TYPE_LONG_OPT { NVM_FORMAT_PI_TYPE_LONG_OPT_STRING, required_argument, NULL, 0 } - #define NVM_FORMAT_PI_LOCATION_LONG_OPT { NVM_FORMAT_PI_LOCATION_LONG_OPT_STRING, required_argument, NULL, 0 } - #define NVM_FORMAT_METADATA_SIZE_LONG_OPT { NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING, required_argument, NULL, 0 } - #define NVM_FORMAT_METADATA_SETTING_LONG_OPT { NVM_FORMAT_METADATA_SETTING_LONG_OPT_STRING, required_argument, NULL, 0 } + #define NVM_FORMAT_NSID_LONG_OPT { NVM_FORMAT_NSID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define NVM_FORMAT_SECURE_ERASE_LONG_OPT { NVM_FORMAT_SECURE_ERASE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define NVM_FORMAT_PI_TYPE_LONG_OPT { NVM_FORMAT_PI_TYPE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define NVM_FORMAT_PI_LOCATION_LONG_OPT { NVM_FORMAT_PI_LOCATION_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define NVM_FORMAT_METADATA_SIZE_LONG_OPT { NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define NVM_FORMAT_METADATA_SETTING_LONG_OPT { NVM_FORMAT_METADATA_SETTING_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define NVM_FORMAT_OPTIONS_LONG_OPTS \ - NVM_FORMAT_NSID_LONG_OPT,NVM_FORMAT_SECURE_ERASE_LONG_OPT,NVM_FORMAT_PI_TYPE_LONG_OPT,NVM_FORMAT_PI_LOCATION_LONG_OPT,NVM_FORMAT_METADATA_SIZE_LONG_OPT,NVM_FORMAT_METADATA_SETTING_LONG_OPT + NVM_FORMAT_NSID_LONG_OPT,NVM_FORMAT_SECURE_ERASE_LONG_OPT,NVM_FORMAT_PI_TYPE_LONG_OPT,NVM_FORMAT_PI_LOCATION_LONG_OPT,NVM_FORMAT_METADATA_SIZE_LONG_OPT,NVM_FORMAT_METADATA_SETTING_LONG_OPT //show format status log #define SHOW_FORMAT_STATUS_LOG_FLAG showFormatStatusLog @@ -1204,7 +1291,7 @@ extern "C" #define FAST_FORMAT_FLAG fastFormat #define FAST_FORMAT_VAR int FAST_FORMAT_FLAG = 0; #define FAST_FORMAT_LONG_OPT_STRING "fastFormat" - #define FAST_FORMAT_LONG_OPT { FAST_FORMAT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FAST_FORMAT_LONG_OPT { FAST_FORMAT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //set sector size #define SET_SECTOR_SIZE_FLAG setSectorSize @@ -1213,7 +1300,7 @@ extern "C" bool setSectorSize = false;\ uint32_t setSectorSizeLogicalSectorSize = 0; #define SET_SECTOR_SIZE_LONG_OPT_STRING "setSectorSize" - #define SET_SECTOR_SIZE_LONG_OPT { SET_SECTOR_SIZE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_SECTOR_SIZE_LONG_OPT { SET_SECTOR_SIZE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //related to formatting and setting sector sizes #define SHOW_SUPPORTED_FORMATS_FLAG showSupportedFormats @@ -1226,19 +1313,19 @@ extern "C" #define FWDL_PORT_MODE_FLAG fwdlPortLockMode #define FWDL_PORT_VARS bool FWDL_PORT_FLAG = false; bool FWDL_PORT_MODE_FLAG = false; #define FWDL_PORT_LONG_OPT_STRING "fwdlPort" - #define FWDL_PORT_LONG_OPT { FWDL_PORT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FWDL_PORT_LONG_OPT { FWDL_PORT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define UDS_PORT_FLAG udsPortLock #define UDS_PORT_MODE_FLAG udsPortLockMode #define UDS_PORT_VARS bool UDS_PORT_FLAG = false; bool UDS_PORT_MODE_FLAG = false; #define UDS_PORT_LONG_OPT_STRING "udsPort" - #define UDS_PORT_LONG_OPT { UDS_PORT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define UDS_PORT_LONG_OPT { UDS_PORT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define IEEE1667_PORT_FLAG ieee1667PortLock #define IEEE1667_PORT_MODE_FLAG ieee1667PortLockMode #define IEEE1667_PORT_VARS bool IEEE1667_PORT_FLAG = false; bool IEEE1667_PORT_MODE_FLAG = false; #define IEEE1667_PORT_LONG_OPT_STRING "ieee1667Port" - #define IEEE1667_PORT_LONG_OPT { IEEE1667_PORT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define IEEE1667_PORT_LONG_OPT { IEEE1667_PORT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //low current spinup #define LOW_CURRENT_SPINUP_FLAG lowCurrentSpinUp @@ -1247,7 +1334,7 @@ extern "C" bool LOW_CURRENT_SPINUP_FLAG = false;\ uint8_t LOW_CURRENT_SPINUP_STATE = 0; #define LOW_CURRENT_SPINUP_LONG_OPT_STRING "lowCurrentSpinup" - #define LOW_CURRENT_SPINUP_LONG_OPT { LOW_CURRENT_SPINUP_LONG_OPT_STRING, required_argument, NULL, 0 } + #define LOW_CURRENT_SPINUP_LONG_OPT { LOW_CURRENT_SPINUP_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //disable data locking #define DISABLE_DATA_LOCKING_FLAG disableDataLocking @@ -1262,7 +1349,7 @@ extern "C" bool SET_APM_LEVEL_FLAG = false;\ uint8_t SET_APM_LEVEL_VALUE_FLAG = 0; #define SET_APM_LEVEL_LONG_OPT_STRING "setAPMLevel" - #define SET_APM_LEVEL_LONG_OPT { SET_APM_LEVEL_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_APM_LEVEL_LONG_OPT { SET_APM_LEVEL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //disable APM #define DISABLE_APM_FLAG disableAPM @@ -1281,12 +1368,18 @@ extern "C" //PUIS Feature enable/disable #define PUIS_FEATURE_FLAG puisFeature + #define PUIS_STATE_VALID_FLAG puisFeatureStateValid #define PUIS_FEATURE_STATE_FLAG puisFeatureState + #define PUIS_FEATURE_INFO_FLAG puisFeatureInfo + #define PUIS_FEATURE_SPINUP_FLAG puisFeatureSpinup #define PUIS_FEATURE_VARS \ bool PUIS_FEATURE_FLAG = false;\ - bool puisFeatureState = false;/* False = disable, true = enable */ + bool PUIS_STATE_VALID_FLAG = false;\ + bool PUIS_FEATURE_STATE_FLAG = false;/* False = disable, true = enable */\ + bool PUIS_FEATURE_INFO_FLAG = false;\ + bool PUIS_FEATURE_SPINUP_FLAG = false; #define PUIS_FEATURE_LONG_OPT_STRING "puisFeature" - #define PUIS_FEATURE_LONG_OPT { PUIS_FEATURE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PUIS_FEATURE_LONG_OPT { PUIS_FEATURE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Show EPC Settings #define SHOW_EPC_SETTINGS_FLAG showEPC @@ -1301,7 +1394,7 @@ extern "C" bool SMART_FEATURE_FLAG = false;\ bool SMART_FEATURE_STATE_FLAG = false; #define SMART_FEATURE_LONG_OPT_STRING "smartFeature" - #define SMART_FEATURE_LONG_OPT { SMART_FEATURE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SMART_FEATURE_LONG_OPT { SMART_FEATURE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Set MRIE mode #define SET_MRIE_MODE_FLAG setMRIEMode @@ -1312,7 +1405,7 @@ extern "C" bool SET_MRIE_MODE_DEFAULT = false;\ uint8_t SET_MRIE_MODE_VALUE = 6; #define SET_MRIE_MODE_LONG_OPT_STRING "setMRIE" - #define SET_MRIE_MODE_LONG_OPT { SET_MRIE_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SET_MRIE_MODE_LONG_OPT { SET_MRIE_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SMART Attribute Autosave #define SMART_ATTR_AUTOSAVE_FEATURE_FLAG smartAttrAutosave @@ -1321,7 +1414,7 @@ extern "C" bool SMART_ATTR_AUTOSAVE_FEATURE_FLAG = false;\ bool SMART_ATTR_AUTOSAVE_FEATURE_STATE_FLAG = false; #define SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT_STRING "smartAttributeAutosave" - #define SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT { SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT { SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SMART Info #define SMART_INFO_FLAG smartInformation @@ -1336,7 +1429,7 @@ extern "C" bool SMART_AUTO_OFFLINE_FEATURE_FLAG = false;\ bool SMART_AUTO_OFFLINE_FEATURE_STATE_FLAG = false; #define SMART_AUTO_OFFLINE_FEATURE_LONG_OPT_STRING "smartAutoOffline" - #define SMART_AUTO_OFFLINE_FEATURE_LONG_OPT { SMART_AUTO_OFFLINE_FEATURE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SMART_AUTO_OFFLINE_FEATURE_LONG_OPT { SMART_AUTO_OFFLINE_FEATURE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Show DST log #define SHOW_DST_LOG_FLAG showDSTLog @@ -1356,18 +1449,18 @@ extern "C" bool GENERIC_LOG_PULL_FLAG = false; \ uint8_t GENERIC_LOG_DATA_SET = 0; #define GENERIC_LOG_LONG_OPT_STRING "pullLog" - #define GENERIC_LOG_LONG_OPT { GENERIC_LOG_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GENERIC_LOG_LONG_OPT { GENERIC_LOG_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define GENERIC_LOG_SUBPAGE_DATA_SET genericLogDataSetSubpage #define GENERIC_LOG_SUBPAGE_VAR \ uint8_t GENERIC_LOG_SUBPAGE_DATA_SET = 0; #define GENERIC_LOG_SUBPAGE_LONG_OPT_STRING "pullSubpage" - #define GENERIC_LOG_SUBPAGE_LONG_OPT { GENERIC_LOG_SUBPAGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GENERIC_LOG_SUBPAGE_LONG_OPT { GENERIC_LOG_SUBPAGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define PULL_LOG_MODE logMode #define PULL_LOG_MODE_VAR eLogPullMode PULL_LOG_MODE = 1; //default as a binary file #define PULL_LOG_MODE_LONG_OPT_STRING "logMode" - #define PULL_LOG_MODE_LONG_OPT { PULL_LOG_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PULL_LOG_MODE_LONG_OPT { PULL_LOG_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Generic SCSI Error history stuff #define LIST_ERROR_HISTORY_FLAG listSupportedErrorHistoryBufferIDs @@ -1381,7 +1474,7 @@ extern "C" bool GENERIC_ERROR_HISTORY_PULL_FLAG = false;\ uint64_t GENERIC_ERROR_HISTORY_BUFFER_ID = 0; #define GENERIC_ERROR_HISTORY_LONG_OPT_STRING "pullErrorHistoryID" - #define GENERIC_ERROR_HISTORY_LONG_OPT { GENERIC_ERROR_HISTORY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define GENERIC_ERROR_HISTORY_LONG_OPT { GENERIC_ERROR_HISTORY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //device statistics (display) #define DEVICE_STATISTICS_FLAG showDeviceStatistics @@ -1396,13 +1489,13 @@ extern "C" uint64_t ZONE_ID_FLAG = UINT64_MAX;\ bool ZONE_ID_ALL_FLAG = false; #define ZONE_ID_LONG_OPT_STRING "zoneID" - #define ZONE_ID_LONG_OPT { ZONE_ID_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ZONE_ID_LONG_OPT { ZONE_ID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define MAX_ZONES_FLAG maxZones #define MAX_ZONES_VAR \ uint32_t MAX_ZONES_FLAG = UINT32_MAX; #define MAX_ZONES_LONG_OPT_STRING "maxZones" - #define MAX_ZONES_LONG_OPT { MAX_ZONES_LONG_OPT_STRING, required_argument, NULL, 0 } + #define MAX_ZONES_LONG_OPT { MAX_ZONES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define REPORT_ZONES_FLAG reportZones #define REPORT_ZONES_REPORTING_MODE_FLAG zoneReportingMode @@ -1410,7 +1503,7 @@ extern "C" bool REPORT_ZONES_FLAG = false;\ int REPORT_ZONES_REPORTING_MODE_FLAG = 0;/*This will be cast to a proper enum type later...*/ #define REPORT_ZONES_LONG_OPT_STRING "reportZones" - #define REPORT_ZONES_LONG_OPT { REPORT_ZONES_LONG_OPT_STRING, required_argument, NULL, 0 } + #define REPORT_ZONES_LONG_OPT { REPORT_ZONES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define CLOSE_ZONE_FLAG zoneClose #define FINISH_ZONE_FLAG zoneFinish @@ -1437,7 +1530,7 @@ extern "C" uint16_t FWDL_SEGMENT_SIZE_FLAG = 64;/*default value*/\ bool FWDL_SEGMENT_SIZE_FROM_USER = false; #define FWDL_SEGMENT_SIZE_LONG_OPT_STRING "fwdlSegSize" - #define FWDL_SEGMENT_SIZE_LONG_OPT { FWDL_SEGMENT_SIZE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FWDL_SEGMENT_SIZE_LONG_OPT { FWDL_SEGMENT_SIZE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //ignore final segment of FWDL for legacy drive compatibility in very specific situations #define FWDL_IGNORE_FINAL_SEGMENT_STATUS_FLAG fwdlIgnoreFinalSegmentStatus @@ -1495,8 +1588,8 @@ extern "C" bool OD_MD_ID_TEST_UNITS_SPECIFIED = false; #define OD_MD_ID_TEST_LONG_OPT_STRING "diameterTest" #define OD_MD_ID_TEST_RANGE_LONG_OPT_STRING "diameterTestRange" - #define OD_MD_ID_TEST_LONG_OPT { OD_MD_ID_TEST_LONG_OPT_STRING, required_argument, NULL, 0 } - #define OD_MD_ID_TEST_RANGE_LONG_OPT { OD_MD_ID_TEST_RANGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define OD_MD_ID_TEST_LONG_OPT { OD_MD_ID_TEST_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define OD_MD_ID_TEST_RANGE_LONG_OPT { OD_MD_ID_TEST_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //hide LBA counter #define HIDE_LBA_COUNTER hideLBACounter @@ -1513,7 +1606,7 @@ extern "C" #define REMOVE_PHYSICAL_ELEMENT_FLAG removePhysicalElement //zero means not set and is not a valid element. Must be non-zero #define REMOVE_PHYSICAL_ELEMENT_VAR uint32_t REMOVE_PHYSICAL_ELEMENT_FLAG = 0; #define REMOVE_PHYSICAL_ELEMENT_LONG_OPT_STRING "removePhysicalElement" - #define REMOVE_PHYSICAL_ELEMENT_LONG_OPT { REMOVE_PHYSICAL_ELEMENT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define REMOVE_PHYSICAL_ELEMENT_LONG_OPT { REMOVE_PHYSICAL_ELEMENT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define REPOPULATE_ELEMENTS_FLAG repopulateElements #define REPOPULATE_ELEMENTS_VAR getOptBool REPOPULATE_ELEMENTS_FLAG = goFalse; @@ -1523,7 +1616,7 @@ extern "C" #define DEPOP_MAX_LBA_FLAG depopulateMaximumLBA #define DEPOP_MAX_LBA_VAR uint64_t DEPOP_MAX_LBA_FLAG = 0; #define DEPOP_MAX_LBA_LONG_OPT_STRING "depopulateMaxLBA" - #define DEPOP_MAX_LBA_LONG_OPT { DEPOP_MAX_LBA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define DEPOP_MAX_LBA_LONG_OPT { DEPOP_MAX_LBA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //TCG Band/Range info #define SHOW_LOCKED_REGIONS showLockedRegions @@ -1533,62 +1626,62 @@ extern "C" //Seagate Power Balance options (SATA only since SAS can use the setPowerConsumption options) #define SEAGATE_POWER_BALANCE_FLAG powerBalanceFeature - #define POWER_BALANCE_MODE powerBalanceMode + #define POWER_BALANCE_MODE powerBalanceMode #define SEAGATE_POWER_BALANCE_ENABLE_FLAG powerBalanceEnable - #define SEAGATE_POWER_BALANCE_LIMITED_FLAG powerBalanceLimited + #define SEAGATE_POWER_BALANCE_LIMITED_FLAG powerBalanceLimited #define SEAGATE_POWER_BALANCE_INFO_FLAG powerBalanceInfo #define SEAGATE_POWER_BALANCE_VARS \ - uint8_t POWER_BALANCE_MODE = 0;\ - bool SEAGATE_POWER_BALANCE_FLAG = false;\ - bool SEAGATE_POWER_BALANCE_ENABLE_FLAG = false;\ - bool SEAGATE_POWER_BALANCE_LIMITED_FLAG = false;\ - bool SEAGATE_POWER_BALANCE_INFO_FLAG = false; + uint8_t POWER_BALANCE_MODE = 0;\ + bool SEAGATE_POWER_BALANCE_FLAG = false;\ + bool SEAGATE_POWER_BALANCE_ENABLE_FLAG = false;\ + bool SEAGATE_POWER_BALANCE_LIMITED_FLAG = false;\ + bool SEAGATE_POWER_BALANCE_INFO_FLAG = false; #define SEAGATE_POWER_BALANCE_LONG_OPT_STRING "powerBalanceFeature" - #define SEAGATE_POWER_BALANCE_LONG_OPT { SEAGATE_POWER_BALANCE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SEAGATE_POWER_BALANCE_LONG_OPT { SEAGATE_POWER_BALANCE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SATA DIPM feature (device initiated power management) #define SATA_DIPM_FLAG sataDIPMFeature #define SATA_DIPM_ENABLE_FLAG sataDIPMEnable #define SATA_DIPM_INFO_FLAG sataDIPMInfo #define SATA_DIPM_VARS \ - bool SATA_DIPM_FLAG = false;\ - bool SATA_DIPM_ENABLE_FLAG = false;\ - bool SATA_DIPM_INFO_FLAG = false; + bool SATA_DIPM_FLAG = false;\ + bool SATA_DIPM_ENABLE_FLAG = false;\ + bool SATA_DIPM_INFO_FLAG = false; #define SATA_DIPM_LONG_OPT_STRING "sataDIPMfeature" - #define SATA_DIPM_LONG_OPT { SATA_DIPM_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SATA_DIPM_LONG_OPT { SATA_DIPM_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SATA DAPS feature (device automatic partial to slumber transitions) #define SATA_DAPS_FLAG sataDAPSFeature #define SATA_DAPS_ENABLE_FLAG sataDAPSEnable #define SATA_DAPS_INFO_FLAG sataDAPSInfo #define SATA_DAPS_VARS \ - bool SATA_DAPS_FLAG = false;\ - bool SATA_DAPS_ENABLE_FLAG = false;\ - bool SATA_DAPS_INFO_FLAG = false; + bool SATA_DAPS_FLAG = false;\ + bool SATA_DAPS_ENABLE_FLAG = false;\ + bool SATA_DAPS_INFO_FLAG = false; #define SATA_DAPS_LONG_OPT_STRING "sataDAPSfeature" - #define SATA_DAPS_LONG_OPT { SATA_DAPS_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SATA_DAPS_LONG_OPT { SATA_DAPS_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SAS Partial bit #define SAS_PARTIAL_FLAG sasPartialBit #define SAS_PARTIAL_ENABLE_FLAG sasPartialEnable #define SAS_PARTIAL_INFO_FLAG sasPartialInfo #define SAS_PARTIAL_VARS \ - bool SAS_PARTIAL_FLAG = false;\ - bool SAS_PARTIAL_ENABLE_FLAG = false;\ - bool SAS_PARTIAL_INFO_FLAG = false; + bool SAS_PARTIAL_FLAG = false;\ + bool SAS_PARTIAL_ENABLE_FLAG = false;\ + bool SAS_PARTIAL_INFO_FLAG = false; #define SAS_PARTIAL_LONG_OPT_STRING "sasPhyPartial" - #define SAS_PARTIAL_LONG_OPT { SAS_PARTIAL_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_PARTIAL_LONG_OPT { SAS_PARTIAL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SAS Slumber bit #define SAS_SLUMBER_FLAG sasSlumberBit #define SAS_SLUMBER_ENABLE_FLAG sasSlumberEnable #define SAS_SLUMBER_INFO_FLAG sasSlumberInfo #define SAS_SLUMBER_VARS \ - bool SAS_SLUMBER_FLAG = false;\ - bool SAS_SLUMBER_ENABLE_FLAG = false;\ - bool SAS_SLUMBER_INFO_FLAG = false; + bool SAS_SLUMBER_FLAG = false;\ + bool SAS_SLUMBER_ENABLE_FLAG = false;\ + bool SAS_SLUMBER_INFO_FLAG = false; #define SAS_SLUMBER_LONG_OPT_STRING "sasPhySlumber" - #define SAS_SLUMBER_LONG_OPT { SAS_SLUMBER_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SAS_SLUMBER_LONG_OPT { SAS_SLUMBER_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //Free fall control #define FREE_FALL_FLAG setFreeFall @@ -1601,7 +1694,24 @@ extern "C" bool FREE_FALL_DISABLE = false;\ uint8_t FREE_FALL_SENSITIVITY = 0; #define FREE_FALL_LONG_OPT_STRING "freeFall" - #define FREE_FALL_LONG_OPT { FREE_FALL_LONG_OPT_STRING, required_argument, NULL, 0 } + #define FREE_FALL_LONG_OPT { FREE_FALL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //ATA Write-read-verify + #define WRV_FLAG setWRV + #define WRV_DISABLE disableWRV + #define WRV_INFO wrvInformation + #define WRV_USER_VALUE wrvUserValue + #define WRV_ALL setWRVallSectors + #define WRV_VENDOR setWRVvendorSpecific + #define WRV_VARS \ + bool WRV_FLAG = false;\ + bool WRV_INFO = false;\ + bool WRV_DISABLE = false;\ + bool WRV_ALL = false;\ + bool WRV_VENDOR = false;\ + uint32_t WRV_USER_VALUE = 0;//user provides sector count. Converted as required by standard by library. + #define WRV_LONG_OPT_STRING "wrv" + #define WRV_LONG_OPT { WRV_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SCSI defect list #define SCSI_DEFECTS_FLAG showSCSIDefects @@ -1615,21 +1725,21 @@ extern "C" int SCSI_DEFECTS_DESCRIPTOR_MODE = 5;//physical CHS as default #define SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING "defectFormat" #define SCSI_DEFECTS_LONG_OPT_STRING "showSCSIDefects" - #define SCSI_DEFECTS_LONG_OPT { SCSI_DEFECTS_LONG_OPT_STRING, required_argument, NULL, 0 } - #define SCSI_DEFECTS_MODE_LONG_OPTS { SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_DEFECTS_LONG_OPT { SCSI_DEFECTS_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define SCSI_DEFECTS_MODE_LONG_OPTS { SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SCSI_DEFECTS_LONG_OPTS SCSI_DEFECTS_LONG_OPT,SCSI_DEFECTS_MODE_LONG_OPTS //logTransferLength #define LOG_TRANSFER_LENGTH_BYTES logTransferLengthBytes #define LOG_TRANSFER_LENGTH_BYTES_VAR uint32_t LOG_TRANSFER_LENGTH_BYTES = 0;/*0 means that the library will decide.*/ #define LOG_TRANSFER_LENGTH_LONG_OPT_STRING "logTransferLength" - #define LOG_TRANSFER_LENGTH_LONG_OPT { LOG_TRANSFER_LENGTH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define LOG_TRANSFER_LENGTH_LONG_OPT { LOG_TRANSFER_LENGTH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //logLength #define LOG_LENGTH_BYTES logLengthBytes #define LOG_LENGTH_BYTES_VAR uint32_t LOG_LENGTH_BYTES = 0;/*0 means that the library will decide.*/ #define LOG_LENGTH_LONG_OPT_STRING "logLength" - #define LOG_LENGTH_LONG_OPT { LOG_LENGTH_LONG_OPT_STRING, required_argument, NULL, 0 } + #define LOG_LENGTH_LONG_OPT { LOG_LENGTH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //FARM Log #define FARM_PULL_FLAG pullFarmLog @@ -1648,7 +1758,7 @@ extern "C" #define SATA_FARM_COPY_TYPE_FLAG sataFarmCopyType #define SATA_FARM_COPY_TYPE_VARS int SATA_FARM_COPY_TYPE_FLAG = 1; // 1 : Disc, 2: Flash (Default is Disc type) #define SATA_FARM_COPY_TYPE_LONG_OPT_STRING "SATAFarmCopyType" - #define SATA_FARM_COPY_TYPE_LONG_OPT { SATA_FARM_COPY_TYPE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SATA_FARM_COPY_TYPE_LONG_OPT { SATA_FARM_COPY_TYPE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //DST Log (standard spec) #define DST_LOG_FLAG pullDSTLog @@ -1688,13 +1798,13 @@ extern "C" bool SHOW_SMART_ERROR_LOG_FLAG = false;\ uint8_t SHOW_SMART_ERROR_LOG_MODE = 0; //0 = summary, 1 = (ext) comp. If a request to see the comp vs ext comp comes in, we can add 2 = ext comp. #define SHOW_SMART_ERROR_LOG_LONG_OPT_STRING "showSMARTErrorLog" - #define SHOW_SMART_ERROR_LOG_LONG_OPT { SHOW_SMART_ERROR_LOG_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SHOW_SMART_ERROR_LOG_LONG_OPT { SHOW_SMART_ERROR_LOG_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //SMART Error log format: detailed vs raw/generic #define SMART_ERROR_LOG_FORMAT_FLAG showSMARTErrorLogGenericFormat //default to false #define SMART_ERROR_LOG_FORMAT_VAR bool SMART_ERROR_LOG_FORMAT_FLAG = false; #define SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING "smartErrorLogFormat" - #define SMART_ERROR_LOG_FORMAT_LONG_OPT { SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SMART_ERROR_LOG_FORMAT_LONG_OPT { SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //These defines make it easy to access the variable name #define ATA_SECURITY_USER_PROVIDED_PASS atSecurityPasswordProvidedByUser @@ -1719,43 +1829,42 @@ extern "C" bool forceUppercase; bool forceLowercase; bool invertCase; - //TODO: add other modifications as we find or hear other that work with some odd BIOS chips. + //add other modifications as we find or hear other that work with some odd BIOS chips. }ataSecPWModifications; #define ATA_SECURITY_PASSWORD_MODIFICATIONS passwordModificationType #define ATA_SECURITY_PASSWORD_MODIFICATIONS_VAR ataSecPWModifications ATA_SECURITY_PASSWORD_MODIFICATIONS = { false, false, false, false, false, false, false, false, false, false }; #define ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING "ataSecPWMod" - #define ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT { ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT { ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //These defines are to put the variable definitions in a file #define ATA_SECURITY_PASSWORD_VARS \ bool ATA_SECURITY_USER_PROVIDED_PASS = false;\ - uint8_t ATA_SECURITY_PASSWORD[32] = { 0 }; \ + DECLARE_ZERO_INIT_ARRAY(uint8_t, ATA_SECURITY_PASSWORD, 32); \ uint8_t ATA_SECURITY_PASSWORD_BYTE_COUNT = 0; #define ATA_SECURITY_PASSWORD_LONG_OPT_STRING "ataSecPassword" //agrs are: password in quotes, SeaChest, or the word empty - #define ATA_SECURITY_PASSWORD_LONG_OPT { ATA_SECURITY_PASSWORD_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_PASSWORD_LONG_OPT { ATA_SECURITY_PASSWORD_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } // #define ATA_SECURITY_USING_MASTER_PW_VAR bool ATA_SECURITY_USING_MASTER_PW = false;//false means user password. True means master password #define ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING "ataSecPassType" - #define ATA_SECURITY_USING_MASTER_PW_LONG_OPT { ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_USING_MASTER_PW_LONG_OPT { ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } - //TODO: This needs to handle the request to do secure erase AND which TYPE of secure erase #define ATA_SECURITY_ERASE_OP performATASecurityErase #define ATA_SECURITY_ERASE_OP_VARS \ bool ATA_SECURITY_ERASE_OP = false; \ bool ATA_SECURITY_ERASE_ENHANCED_FLAG = false;//false = normal erase, true - enhanced erase #define ATA_SECURITY_ERASE_OP_LONG_OPT_STRING "ataSecureErase" - #define ATA_SECURITY_ERASE_OP_LONG_OPT { ATA_SECURITY_ERASE_OP_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_ERASE_OP_LONG_OPT { ATA_SECURITY_ERASE_OP_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ATA_SECURITY_MASTER_PW_CAPABILITY_VAR bool ATA_SECURITY_MASTER_PW_CAPABILITY = false;//false = high, true = maximum #define ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT_STRING "ataSecCapability" - #define ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT { ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT { ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ATA_SECURITY_MASTER_PW_ID_VAR uint16_t ATA_SECURITY_MASTER_PW_ID = 0;//value set by the user #define ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING "ataSecMasterPWID" - #define ATA_SECURITY_MASTER_PW_ID_LONG_OPT { ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_MASTER_PW_ID_LONG_OPT { ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING "ataSATsecurityProtocol" - #define ATA_SECURITY_FORCE_SAT_LONG_OPT { ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_SECURITY_FORCE_SAT_LONG_OPT { ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ATA_SECURITY_FORCE_SAT_VARS \ bool ATA_SECURITY_FORCE_SAT_VALID = false;\ bool ATA_SECURITY_FORCE_SAT = false;//false = turn OFF SAT security protocol commands. true = turn ON SAT security protocol commands @@ -1801,7 +1910,7 @@ extern "C" uint8_t SCSI_MP_RESET_PAGE_NUMBER = 0;\ uint8_t SCSI_MP_RESET_SUBPAGE_NUMBER = 0; #define SCSI_MP_RESET_LONG_OPT_STRING "scsiMPReset" - #define SCSI_MP_RESET_LONG_OPT { SCSI_MP_RESET_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_MP_RESET_LONG_OPT { SCSI_MP_RESET_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SCSI_MP_RESTORE_OP restoreSCSIModePage #define SCSI_MP_RESTORE_PAGE_NUMBER restoreModePageNumber @@ -1811,7 +1920,7 @@ extern "C" uint8_t SCSI_MP_RESTORE_PAGE_NUMBER = 0;\ uint8_t SCSI_MP_RESTORE_SUBPAGE_NUMBER = 0; #define SCSI_MP_RESTORE_LONG_OPT_STRING "scsiMPRestore" - #define SCSI_MP_RESTORE_LONG_OPT { SCSI_MP_RESTORE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_MP_RESTORE_LONG_OPT { SCSI_MP_RESTORE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SCSI_MP_SAVE_OP saveSCSIModePage #define SCSI_MP_SAVE_PAGE_NUMBER saveModePageNumber @@ -1821,7 +1930,7 @@ extern "C" uint8_t SCSI_MP_SAVE_PAGE_NUMBER = 0;\ uint8_t SCSI_MP_SAVE_SUBPAGE_NUMBER = 0; #define SCSI_MP_SAVE_LONG_OPT_STRING "scsiMPSave" - #define SCSI_MP_SAVE_LONG_OPT { SCSI_MP_SAVE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_MP_SAVE_LONG_OPT { SCSI_MP_SAVE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //show scsi mode page (TODO: different output modes) output modes: classic vs "neat" or some other name... #define SCSI_SHOW_MP_OP showSCSIModePage @@ -1838,12 +1947,13 @@ extern "C" #define SCSI_SHOW_MP_MPC_LONG_OPT_STRING "showSCSIMPControl" #define SCSI_SHOW_MP_LONG_OPT_STRING "showSCSIMP" #define SCSI_SHOW_MP_BUFFER_MODE_LONG_OPT_STRING "showMPOutputMode" - #define SCSI_SHOW_MP_LONG_OPT { SCSI_SHOW_MP_LONG_OPT_STRING, required_argument, NULL, 0 } - #define SCSI_SHOW_MP_MPC_LONG_OPT { SCSI_SHOW_MP_MPC_LONG_OPT_STRING, required_argument, NULL, 0 } - #define SCSI_SHOW_MP_BUFFER_MODE_LONG_OPT { SCSI_SHOW_MP_BUFFER_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_SHOW_MP_LONG_OPT { SCSI_SHOW_MP_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define SCSI_SHOW_MP_MPC_LONG_OPT { SCSI_SHOW_MP_MPC_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define SCSI_SHOW_MP_BUFFER_MODE_LONG_OPT { SCSI_SHOW_MP_BUFFER_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SCSI_SHOW_MP_LONG_OPTS SCSI_SHOW_MP_LONG_OPT,SCSI_SHOW_MP_MPC_LONG_OPT,SCSI_SHOW_MP_BUFFER_MODE_LONG_OPT //setting a SCSI mode page + #define SCSI_SET_MP_FILENAME_LEN 4096 #define SCSI_SET_MP_OP setSCSIModePage #define SCSI_SET_MP_FILENAME setSCSIModePageFilename #define SCSI_SET_MP_PAGE_NUMBER setSCSIModePageNumber @@ -1852,10 +1962,9 @@ extern "C" #define SCSI_SET_MP_BIT setSCSIMPBit #define SCSI_SET_MP_FIELD_LEN_BITS setSCSIMPFieldLen #define SCSI_SET_MP_FIELD_VALUE setSCSIMPFieldVal - #define SCSI_SET_MP_SSCANF_FILE_FORMAT_STR "file=%4095s" //one less that total array size to make sure there is room without a warning for a null terminating character-TJE #define SCSI_SET_MP_VARS \ bool SCSI_SET_MP_OP = false;\ - char SCSI_SET_MP_FILENAME[4096] = { 0 };\ + DECLARE_ZERO_INIT_ARRAY(char, SCSI_SET_MP_FILENAME, SCSI_SET_MP_FILENAME_LEN);\ uint8_t SCSI_SET_MP_PAGE_NUMBER = 0;\ uint8_t SCSI_SET_MP_SUBPAGE_NUMBER = 0;\ uint16_t SCSI_SET_MP_BYTE = 0;\ @@ -1863,7 +1972,7 @@ extern "C" uint8_t SCSI_SET_MP_FIELD_LEN_BITS = 0;\ uint64_t SCSI_SET_MP_FIELD_VALUE = 0; #define SCSI_SET_MP_LONG_OPT_STRING "setSCSIMP" //mp[-sp]:byte:highestBit:fieldWidthInBits=value OR file=filename.txt - #define SCSI_SET_MP_LONG_OPT { SCSI_SET_MP_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_SET_MP_LONG_OPT { SCSI_SET_MP_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //reset a SCSI Log page #define SCSI_RESET_LP_OP resetSCSILogPage @@ -1877,8 +1986,8 @@ extern "C" int SCSI_RESET_LP_LPC = 1; /*default to the thresholds*/ #define SCSI_RESET_LP_LONG_OPT_STRING "scsiLPReset" #define SCSI_RESET_LP_PAGE_LONG_OPT_STRING "scsiLPResetPage" - #define SCSI_RESET_LP_LONG_OPT { SCSI_RESET_LP_LONG_OPT_STRING, required_argument, NULL, 0 } - #define SCSI_RESET_LP_PAGE_LONG_OPT {SCSI_RESET_LP_PAGE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define SCSI_RESET_LP_LONG_OPT { SCSI_RESET_LP_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define SCSI_RESET_LP_PAGE_LONG_OPT {SCSI_RESET_LP_PAGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define SCSI_RESET_LP_LONG_OPTS SCSI_RESET_LP_LONG_OPT,SCSI_RESET_LP_PAGE_LONG_OPT //power telemetry options @@ -1898,9 +2007,9 @@ extern "C" uint16_t REQUEST_POWER_TELEMETRY_MEASUREMENT_TIME_SECONDS = 0;\ int REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE = 0; #define REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT_STRING "powerMeasurementMode" - #define REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT { REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT { REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT_STRING "requestPowerMeasurement" - #define REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT { REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT { REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define REQUEST_POWER_TELEMETRY_MEASUREMENT_OPTIONS REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT,REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT //pull the power telemetry data to a file @@ -1912,14 +2021,14 @@ extern "C" //Seagate SATA quick format - This may have different requirements to support. Not supported on all Seagate products. #define SEAGATE_SATA_QUICK_FORMAT sataQuickFormat #define SEAGATE_SATA_QUICK_FORMAT_VARS \ - getOptBool SEAGATE_SATA_QUICK_FORMAT = goFalse; + getOptBool SEAGATE_SATA_QUICK_FORMAT = goFalse; #define SEAGATE_SATA_QUICK_FORMAT_LONG_OPT_STRING "seagateQuickFormat" #define SEAGATE_SATA_QUICK_FORMAT_LONG_OPT { SEAGATE_SATA_QUICK_FORMAT_LONG_OPT_STRING, no_argument, &SEAGATE_SATA_QUICK_FORMAT, goTrue } //Force option can be used to try overriding support detection, or other things. May not be supported on all operations. #define FORCE_FLAG forceThisToHappen #define FORCE_VAR \ - getOptBool FORCE_FLAG = goFalse; + getOptBool FORCE_FLAG = goFalse; #define FORCE_LONG_OPT_STRING "force" #define FORCE_LONG_OPT { FORCE_LONG_OPT_STRING, no_argument, &FORCE_FLAG, goTrue } @@ -1929,6 +2038,12 @@ extern "C" #define SHOW_CONCURRENT_RANGES_LONG_OPT_STRING "showConcurrentRanges" #define SHOW_CONCURRENT_RANGES_LONG_OPT { SHOW_CONCURRENT_RANGES_LONG_OPT_STRING, no_argument, &SHOW_CONCURRENT_RANGES, goTrue } + //SATA Phy event counters + #define SHOW_PHY_EVENT_COUNTERS showSataPhyEventCounters + #define SHOW_PHY_EVENT_COUNTERS_VAR getOptBool SHOW_PHY_EVENT_COUNTERS = goFalse; + #define SHOW_PHY_EVENT_COUNTERS_LONG_OPT_STRING "showPhyEvents" + #define SHOW_PHY_EVENT_COUNTERS_LONG_OPT { SHOW_PHY_EVENT_COUNTERS_LONG_OPT_STRING, no_argument, &SHOW_PHY_EVENT_COUNTERS, goTrue } + //SCSI/NVMe reservations #define SHOW_RESERVATION_CAPABILITIES showReservationCapabilities #define SHOW_RESERVATION_CAPABILITIES_VAR getOptBool SHOW_RESERVATION_CAPABILITIES = goFalse; @@ -1956,15 +2071,15 @@ extern "C" bool PERSISTENT_RESREVATION_KEY_VALID = false;\ uint64_t PERSISTENT_RESERVATION_KEY = 0; #define PERSISTENT_RESERVATION_KEY_LONG_OPT_STRING "prKey" - #define PERSISTENT_RESERVATION_KEY_LONG_OPT { PERSISTENT_RESERVATION_KEY_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PERSISTENT_RESERVATION_KEY_LONG_OPT { PERSISTENT_RESERVATION_KEY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define PERSISTENT_RESERVATION_TYPE prType #define PERSISTENT_RESREVATION_TYPE_VALID prTypeValid #define PERSISTENT_RESERVATION_TYPE_VARS \ bool PERSISTENT_RESREVATION_TYPE_VALID = false;\ - uint64_t PERSISTENT_RESERVATION_TYPE = 0; + int PERSISTENT_RESERVATION_TYPE = 0; #define PERSISTENT_RESERVATION_TYPE_LONG_OPT_STRING "prType" - #define PERSISTENT_RESERVATION_TYPE_LONG_OPT { PERSISTENT_RESERVATION_TYPE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PERSISTENT_RESERVATION_TYPE_LONG_OPT { PERSISTENT_RESERVATION_TYPE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define PERSISTENT_RESERVATION_ATP prATP #define PERSISTENT_RESERVATION_ATP_VAR getOptBool PERSISTENT_RESERVATION_ATP = goFalse; @@ -2012,14 +2127,14 @@ extern "C" bool PERSISTENT_RESERVATION_PREEMPT = false;\ uint64_t PERSISTENT_RESERVATION_PREEMPT_KEY = 0; #define PERSISTENT_RESERVATION_PREEMPT_LONG_OPT_STRING "prPreempt" - #define PERSISTENT_RESERVATION_PREEMPT_LONG_OPT { PERSISTENT_RESERVATION_PREEMPT_LONG_OPT_STRING, required_argument, NULL, 0 } + #define PERSISTENT_RESERVATION_PREEMPT_LONG_OPT { PERSISTENT_RESERVATION_PREEMPT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define PERSISTENT_RESERVATION_PREEMPT_ABORT prPreemptAbort #define PERSISTENT_RESERVATION_PREEMPT_ABORT_VAR getOptBool PERSISTENT_RESERVATION_PREEMPT_ABORT = goFalse; #define PERSISTENT_RESERVATION_PREEMPT_ABORT_LONG_OPT_STRING "prPreemptAbort" #define PERSISTENT_RESERVATION_PREEMPT_ABORT_LONG_OPT { PERSISTENT_RESERVATION_PREEMPT_ABORT_LONG_OPT_STRING, no_argument, &PERSISTENT_RESERVATION_PREEMPT_ABORT, goTrue } - - //ATA Device Configuration Overlay feature options + + //ATA Device Configuration Overlay feature options #define ATA_DCO_RESTORE ataDCORestoreSettingsToFactory #define ATA_DCO_RESTORE_VAR getOptBool ATA_DCO_RESTORE = goFalse; #define ATA_DCO_RESTORE_LONG_OPT_STRING "dcoRestore" @@ -2041,7 +2156,7 @@ extern "C" bool ATA_DCO_SETMAXLBA = false;\ uint64_t ATA_DCO_SETMAXLBA_VALUE = 0; #define ATA_DCO_SETMAXLBA_LONG_OPT_STRING "dcoSetMaxLBA" - #define ATA_DCO_SETMAXLBA_LONG_OPT { ATA_DCO_SETMAXLBA_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_DCO_SETMAXLBA_LONG_OPT { ATA_DCO_SETMAXLBA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } //set highest reported DMA mode (MWDMA or UDMA #) #define ATA_DCO_SETMAXMODE ataDCOSetMaxMode @@ -2061,7 +2176,7 @@ extern "C" #define ATA_DCO_MODE_UDMA4 "udma4" #define ATA_DCO_MODE_UDMA5 "udma5" #define ATA_DCO_MODE_UDMA6 "udma6" - #define ATA_DCO_SETMAXMODE_LONG_OPT { ATA_DCO_SETMAXMODE_LONG_OPT_STRING, required_argument, NULL, 0 } + #define ATA_DCO_SETMAXMODE_LONG_OPT { ATA_DCO_SETMAXMODE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } #define ATA_DCO_DISABLE_FEATURES ataDCODisableFeatures #define ATA_DCO_DISABLE_FEATURES_VALUE ataDCOValueBitField @@ -2097,9 +2212,289 @@ extern "C" #define ATA_DCO_FEATURE_OPTION_DSM "dsm" #define ATA_DCO_FEATURE_OPTION_TRIM "trim" #define ATA_DCO_FEATURE_OPTION_EPC "epc" - #define ATA_DCO_DISABLE_FEEATURES_LONG_OPT { ATA_DCO_DISABLE_FEEATURES_LONG_OPT_STRING, required_argument, NULL, 0 } - - #define LONG_OPT_TERMINATOR { NULL, 0, NULL, 0 } + #define ATA_DCO_DISABLE_FEEATURES_LONG_OPT { ATA_DCO_DISABLE_FEEATURES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //raw CDB related flags + #define RAW_CDB_LEN_FLAG rawCDBLength + #define RAW_CDB_LEN_VAR \ + uint8_t RAW_CDB_LEN_FLAG = 0; + #define RAW_CDB_LEN_LONG_OPT_STRING "cdbLen" + #define RAW_CDB_LEN_LONG_OPT { RAW_CDB_LEN_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_CDB_ARRAY rawCDB + #define RAW_CDB_ARRAY_VAR \ + DECLARE_ZERO_INIT_ARRAY(uint8_t, RAW_CDB_ARRAY, UINT8_MAX); + #define RAW_CDB_ARRAY_LONG_OPT_STRING "cdb" + #define RAW_CDB_ARRAY_LONG_OPT { RAW_CDB_ARRAY_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //raw TFR related flags + #define RAW_TFR_SIZE_FLAG rawTFRLength + #define RAW_TFR_SIZE_VAR \ + uint8_t RAW_TFR_SIZE_FLAG = 0; //48 for ext command, and 28 for short command + #define RAW_TFR_SIZE_LONG_OPT_STRING "tfrSize" + #define RAW_TFR_SIZE_LONG_OPT { RAW_TFR_SIZE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //raw tfr registers + #define RAW_TFR_COMMAND tfrCommand + #define RAW_TFR_FEATURE tfrFeature + #define RAW_TFR_FEATURE_EXT tfrFeatureExt + #define RAW_TFR_LBA_LOW tfrLBALo + #define RAW_TFR_LBA_MID tfrLBAMid + #define RAW_TFR_LBA_HIGH tfrLBAHigh + #define RAW_TFR_LBA_LOW_EXT tfrLBALoExt + #define RAW_TFR_LBA_MID_EXT tfrLBAMidExt + #define RAW_TFR_LBA_HIGH_EXT tfrLBAHighExt + #define RAW_TFR_DEVICE_HEAD tfrDeviceHead + #define RAW_TFR_SECTOR_COUNT tfrSectorCount + #define RAW_TFR_SECTOR_COUNT_EXT tfrSectorCountExt + #define RAW_TFR_ICC tfrICC + #define RAW_TFR_AUX1 tfrAux1 + #define RAW_TFR_AUX2 tfrAux2 + #define RAW_TFR_AUX3 tfrAux3 + #define RAW_TFR_AUX4 tfrAux4 + #define RAW_TFR_VARS \ + uint8_t RAW_TFR_COMMAND = 0;\ + uint8_t RAW_TFR_FEATURE = 0;\ + uint8_t RAW_TFR_FEATURE_EXT = 0;\ + uint8_t RAW_TFR_LBA_LOW = 0;\ + uint8_t RAW_TFR_LBA_MID = 0;\ + uint8_t RAW_TFR_LBA_HIGH = 0;\ + uint8_t RAW_TFR_LBA_LOW_EXT = 0;\ + uint8_t RAW_TFR_LBA_MID_EXT = 0;\ + uint8_t RAW_TFR_LBA_HIGH_EXT = 0;\ + uint8_t RAW_TFR_DEVICE_HEAD = 0xA0/*backwards compatible by default*/;\ + uint8_t RAW_TFR_SECTOR_COUNT = 0;\ + uint8_t RAW_TFR_SECTOR_COUNT_EXT = 0;\ + uint8_t RAW_TFR_ICC = 0;\ + uint8_t RAW_TFR_AUX1 = 0;\ + uint8_t RAW_TFR_AUX2 = 0;\ + uint8_t RAW_TFR_AUX3 = 0;\ + uint8_t RAW_TFR_AUX4 = 0; + + #define RAW_TFR_COMMAND_LONG_OPT_STRING "command" + #define RAW_TFR_FEATURE_LONG_OPT_STRING "feature" + #define RAW_TFR_FEATURE_EXT_LONG_OPT_STRING "featureExt" + #define RAW_TFR_FEATURE_FULL_LONG_OPT_STRING "featFull" //will break apart into the two separate feature regs, just allowing this in case it's simpler to use + #define RAW_TFR_LBA_LOW_LONG_OPT_STRING "lbaLow" + #define RAW_TFR_LBA_MID_LONG_OPT_STRING "lbaMid" + #define RAW_TFR_LBA_HIGH_LONG_OPT_STRING "lbaHigh" + #define RAW_TFR_LBA_LOW_EXT_LONG_OPT_STRING "lbaLowExt" + #define RAW_TFR_LBA_MID_EXT_LONG_OPT_STRING "lbaMidExt" + #define RAW_TFR_LBA_HIGH_EXT_LONG_OPT_STRING "lbaHighExt" + #define RAW_TFR_LBA_FULL_LONG_OPT_STRING "fullLBA" //will be broken apart into all separate sections based on the passed in value...to help simplify cli when they don't need specific bits set to specific things +/* + #define RAW_TFR_SECTOR_NUM_LONG_OPT_STRING "sectorNum" + #define RAW_TFR_SECTOR_NUM_LONG_OPT_STRING "sectorNumExt" + #define RAW_TFR_CYLINDER_LOW_LONG_OPT_STRING "cylinderLow" + #define RAW_TFR_CYLINDER_HIGH_LONG_OPT_STRING "cylinderHigh" + #define RAW_TFR_CYLINDER_LOW_EXT_LONG_OPT_STRING "cylinderLowExt" + #define RAW_TFR_CYLINDER_HIGH_EXT_LONG_OPT_STRING "cylinderHighExt" + #define RAW_TFR_CHS_FULL "chsFull" +*/ + #define RAW_TFR_DEVICE_HEAD_LONG_OPT_STRING "deviceHead" + #define RAW_TFR_SECTOR_COUNT_LONG_OPT_STRING "sectorCount" + #define RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT_STRING "sectorCountExt" + #define RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT_STRING "sectFull" //will break apart into the two separate feature regs, just allowing this in case it's simpler to use + #define RAW_TFR_ICC_LONG_OPT_STRING "icc" + #define RAW_TFR_AUX1_LONG_OPT_STRING "aux1" + #define RAW_TFR_AUX2_LONG_OPT_STRING "aux2" + #define RAW_TFR_AUX3_LONG_OPT_STRING "aux3" + #define RAW_TFR_AUX4_LONG_OPT_STRING "aux4" + #define RAW_TFR_AUX_FULL_LONG_OPT_STRING "auxFull" //will break apart into the two separate feature regs, just allowing this in case it's simpler to use + #define RAW_TFR_LBA_MODE_BIT_LONG_OPT_STRING "lbaMode" //sets the LBA mode bit in device/head register + +//TODO: add other options with legacy names like cylinder, head, sector, etc +//TODO: multiple count option for read/write multiple commands? + + #define RAW_TFR_COMMAND_LONG_OPT { RAW_TFR_COMMAND_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_FEATURE_LONG_OPT { RAW_TFR_FEATURE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_FEATURE_EXT_LONG_OPT { RAW_TFR_FEATURE_EXT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_FEATURE_FULL_LONG_OPT { RAW_TFR_FEATURE_FULL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_LOW_LONG_OPT { RAW_TFR_LBA_LOW_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_MID_LONG_OPT { RAW_TFR_LBA_MID_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_HIGH_LONG_OPT { RAW_TFR_LBA_HIGH_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_LOW_EXT_LONG_OPT { RAW_TFR_LBA_LOW_EXT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_MID_EXT_LONG_OPT { RAW_TFR_LBA_MID_EXT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_HIGH_EXT_LONG_OPT { RAW_TFR_LBA_HIGH_EXT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_FULL_LONG_OPT { RAW_TFR_LBA_FULL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_DEVICE_HEAD_LONG_OPT { RAW_TFR_DEVICE_HEAD_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_LBA_MODE_BIT_LONG_OPT { RAW_TFR_LBA_MODE_BIT_LONG_OPT_STRING, no_argument, M_NULLPTR, 0 } + #define RAW_TFR_SECTOR_COUNT_LONG_OPT { RAW_TFR_SECTOR_COUNT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT { RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT { RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_ICC_LONG_OPT { RAW_TFR_ICC_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_AUX1_LONG_OPT { RAW_TFR_AUX1_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_AUX2_LONG_OPT { RAW_TFR_AUX2_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_AUX3_LONG_OPT { RAW_TFR_AUX3_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_AUX4_LONG_OPT { RAW_TFR_AUX4_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_AUX_FULL_LONG_OPT { RAW_TFR_AUX_FULL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + #define RAW_TFR_REGITER_LONG_OPTS \ + RAW_TFR_COMMAND_LONG_OPT, RAW_TFR_FEATURE_LONG_OPT, RAW_TFR_FEATURE_EXT_LONG_OPT, RAW_TFR_FEATURE_FULL_LONG_OPT, RAW_TFR_LBA_LOW_LONG_OPT, RAW_TFR_LBA_MID_LONG_OPT, RAW_TFR_LBA_HIGH_LONG_OPT, \ + RAW_TFR_LBA_LOW_EXT_LONG_OPT, RAW_TFR_LBA_MID_EXT_LONG_OPT, RAW_TFR_LBA_HIGH_EXT_LONG_OPT, RAW_TFR_LBA_FULL_LONG_OPT, RAW_TFR_DEVICE_HEAD_LONG_OPT, RAW_TFR_LBA_MODE_BIT_LONG_OPT, RAW_TFR_SECTOR_COUNT_LONG_OPT, \ + RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT, RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT, RAW_TFR_ICC_LONG_OPT, RAW_TFR_AUX1_LONG_OPT, RAW_TFR_AUX2_LONG_OPT, RAW_TFR_AUX3_LONG_OPT, RAW_TFR_AUX4_LONG_OPT, RAW_TFR_AUX_FULL_LONG_OPT + + #define RAW_TFR_PROTOCOL tfrProtocol + #define RAW_TFR_PROTOCOL_VAR int RAW_TFR_PROTOCOL = -1; + #define RAW_TFR_PROTOCOL_LONG_OPT_STRING "tfrProtocol" + #define RAW_TFR_PROTOCOL_LONG_OPT { RAW_TFR_PROTOCOL_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_TFR_XFER_LENGTH_LOCATION tfrLengthLocation + #define RAW_TFR_XFER_LENGTH_LOCATION_VAR int RAW_TFR_XFER_LENGTH_LOCATION = -1; + #define RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT_STRING "tfrXferLengthReg" + #define RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT { RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_TFR_CHECK_CONDITION tfrCheckCondition + #define RAW_TFR_CHECK_CONDITION_VAR getOptBool RAW_TFR_CHECK_CONDITION = goFalse; + #define RAW_TFR_CHECK_CONDITION_LONG_OPT_STRING "tfrSetChkCond" + #define RAW_TFR_CHECK_CONDITION_LONG_OPT { RAW_TFR_CHECK_CONDITION_LONG_OPT_STRING, no_argument, &RAW_TFR_CHECK_CONDITION, goTrue } + + #define RAW_TFR_BYTE_BLOCK tfrByteBlock + #define RAW_TFR_BYTE_BLOCK_VAR int RAW_TFR_BYTE_BLOCK = -1;//0 will mean no-data, 1 = byte count, 512 = 512B blocks, UINT8_MAX = logical sector size + #define RAW_TFR_BYTE_BLOCK_LONG_OPT_STRING "tfrByteBlock" + #define RAW_TFR_BYTE_BLOCK_LONG_OPT { RAW_TFR_BYTE_BLOCK_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //shared raw flags + #define RAW_DATA_LEN_FLAG rawDataLength + #define RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG rawDataLengthBlocks + #define RAW_DATA_LEN_VARS \ + uint32_t RAW_DATA_LEN_FLAG = 0;\ + bool RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG = false; + #define RAW_DATA_LEN_LONG_OPT_STRING "dataLen" + #define RAW_DATA_LEN_LONG_OPT { RAW_DATA_LEN_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_DATA_DIRECTION_FLAG rawDataDirection + #define RAW_DATA_DIRECTION_VAR \ + int RAW_DATA_DIRECTION_FLAG = -1;//set to somthing invalid. this int should cast to the data direction enum for us just fine.... + #define RAW_DATA_DIRECTION_LONG_OPT_STRING "dataDir" + #define RAW_DATA_DIRECTION_LONG_OPT { RAW_DATA_DIRECTION_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_TIMEOUT_FLAG rawTimeout + #define RAW_TIMEOUT_VAR \ + uint32_t RAW_TIMEOUT_FLAG = 15 * 1000;//15 seconds is the default + #define RAW_TIMEOUT_LONG_OPT_STRING "timeout" + #define RAW_TIMEOUT_LONG_OPT { RAW_TIMEOUT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_OUTPUT_FILE_FLAG rawOutFile + #define RAW_OUTPUT_FILE_NAME_FLAG rawOutFileName + #define RAW_OUTPUT_FILE_VARS \ + const char* RAW_OUTPUT_FILE_NAME_FLAG = M_NULLPTR;\ + secureFileInfo *RAW_OUTPUT_FILE_FLAG = M_NULLPTR; + #define RAW_OUTPUT_FILE_LONG_OPT_STRING "outputFile" + #define RAW_OUTPUT_FILE_LONG_OPT { RAW_OUTPUT_FILE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_INPUT_FILE_FLAG rawInFile + #define RAW_INPUT_FILE_NAME_FLAG rawInFileName + #define RAW_INPUT_FILE_VARS \ + const char* RAW_INPUT_FILE_NAME_FLAG = M_NULLPTR;\ + secureFileInfo *RAW_INPUT_FILE_FLAG = M_NULLPTR; + #define RAW_INPUT_FILE_LONG_OPT_STRING "inputFile" + #define RAW_INPUT_FILE_LONG_OPT { RAW_INPUT_FILE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RAW_INPUT_FILE_OFFSET_FLAG rawInFileOffset + #define RAW_INPUT_OFFSET_ADJUST_BY_BLOCKS_FLAG rawInOffsetBlocks + #define RAW_INPUT_FILE_OFFSET_VAR \ + int64_t RAW_INPUT_FILE_OFFSET_FLAG = 0; \ + getOptBool RAW_INPUT_OFFSET_ADJUST_BY_BLOCKS_FLAG = goFalse; + #define RAW_INPUT_FILE_OFFSET_LONG_OPT_STRING "inputOffset" + #define RAW_INPUT_FILE_OFFSET_LONG_OPT { RAW_INPUT_FILE_OFFSET_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //check Pending List count + #define CHECK_PENDING_LIST_COUNT_FLAG checkPendingListCount + #define CHECK_PENDING_LIST_COUNT_VALUE pendlingListCountToCheck + #define CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG checkPendingListLogicalCount + #define CHECK_PENDING_LIST_COUNT_VARS \ + bool CHECK_PENDING_LIST_COUNT_FLAG = false;\ + bool CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG = false; /*By default we check for bad Physical sector counts, but the drive reports in logical, so this is an override flag*/\ + uint32_t CHECK_PENDING_LIST_COUNT_VALUE = UINT32_MAX; + #define CHECK_PENDING_LIST_COUNT_LONG_OPT_STRING "checkPendingListCount" + #define CHECK_PENDING_LIST_COUNT_LONG_OPT { CHECK_PENDING_LIST_COUNT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //check Grown List count + #define CHECK_GROWN_LIST_COUNT_FLAG checkGrownListCount + #define CHECK_GROWN_LIST_COUNT_VALUE grownListCountToCheck + #define CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG checkGrownListLogicalCount + #define CHECK_GROWN_LIST_COUNT_VARS \ + bool CHECK_GROWN_LIST_COUNT_FLAG = false;\ + bool CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG = false; /*By default we check for bad Physical sector counts, but the drive reports in logical, so this is an override flag*/\ + uint32_t CHECK_GROWN_LIST_COUNT_VALUE = UINT32_MAX; + #define CHECK_GROWN_LIST_COUNT_LONG_OPT_STRING "checkGrownListCount" + #define CHECK_GROWN_LIST_COUNT_LONG_OPT { CHECK_GROWN_LIST_COUNT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //show pending list + #define SHOW_PENDING_LIST showPendingList + #define SHOW_PENDING_LIST_VAR getOptBool SHOW_PENDING_LIST = goFalse; + #define SHOW_PENDING_LIST_LONG_OPT_STRING "showPendingList" + #define SHOW_PENDING_LIST_LONG_OPT { SHOW_PENDING_LIST_LONG_OPT_STRING, no_argument, &SHOW_PENDING_LIST, goTrue } + + #define CREATE_UNCORRECTABLE_FLAG createUncorrectable + #define CREATE_UNCORRECTABLE_VAR \ + bool CREATE_UNCORRECTABLE_FLAG = false; + #define CREATE_UNCORRECTABLE_LBA_FLAG uncorrectableLBA + #define CREATE_UNCORRECTABLE_LBA_VAR \ + uint64_t CREATE_UNCORRECTABLE_LBA_FLAG = UINT64_MAX; + #define CREATE_UNCORRECTABLE_LONG_OPT_STRING "psuedoUncorrectable" + #define CREATE_UNCORRECTABLE_LONG_OPT { CREATE_UNCORRECTABLE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define UNCORRECTABLE_RANGE_FLAG uncorrectableRange + #define UNCORRECTABLE_RANGE_VAR \ + uint64_t UNCORRECTABLE_RANGE_FLAG = 1;/*set to one for a default value of a single sector*/ + #define UNCORRECTABLE_RANGE_LONG_OPT_STRING "uncorrectableRange" + #define UNCORRECTABLE_RANGE_LONG_OPT { UNCORRECTABLE_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define RANDOM_UNCORRECTABLES_FLAG randomUncorrectableCount + #define RANDOM_UNCORRECTABLES_VAR \ + uint16_t RANDOM_UNCORRECTABLES_FLAG = 0; + #define RANDOM_UNCORRECTABLES_LONG_OPT_STRING "randomUncorrectables" + #define RANDOM_UNCORRECTABLES_LONG_OPT { RANDOM_UNCORRECTABLES_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define FLAG_UNCORRECTABLES_FLAG flagUncorrectable + #define FLAG_UNCORRECTABLES_VAR \ + getOptBool FLAG_UNCORRECTABLES_FLAG = goFalse; + #define FLAG_UNCORRECTABLE_LONG_OPT_STRING "flaggedUncorrectable" + #define FLAG_UNCORRECTABLE_LONG_OPT { FLAG_UNCORRECTABLE_LONG_OPT_STRING, no_argument, &FLAG_UNCORRECTABLES_FLAG, goTrue } + + #define READ_UNCORRECTABLES_FLAG readUncorrectables + #define READ_UNCORRECTABLES_VAR \ + bool READ_UNCORRECTABLES_FLAG = true;/*this is set to true by default. The command line flag is used to disable this functionality*/ + #define DISABLE_READ_UNCORRECTABLES_LONG_OPT_STRING "disableReadUncorrectables" + #define DISABLE_READ_UNCORRECTABLES_LONG_OPT { DISABLE_READ_UNCORRECTABLES_LONG_OPT_STRING, no_argument, M_NULLPTR, 0 } + + #define CORRUPT_LBA_FLAG performCorruptLBA + #define CORRUPT_LBA_LBA lbaToCorrupt + #define CORRUPT_LBA_VAR \ + bool CORRUPT_LBA_FLAG = false;\ + uint64_t CORRUPT_LBA_LBA = 0; + #define CORRUPT_LBA_LONG_OPT_STRING "corruptLBA" + #define CORRUPT_LBA_LONG_OPT { CORRUPT_LBA_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define CORRUPT_LBA_RANGE_FLAG lbaRangeToCorrupt + #define CORRUPT_LBA_RANGE_VAR uint64_t CORRUPT_LBA_RANGE_FLAG = 1; + #define CORRUPT_LBA_RANGE_LONG_OPT_STRING "corruptRange" + #define CORRUPT_LBA_RANGE_LONG_OPT { CORRUPT_LBA_RANGE_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define CORRUPT_RANDOM_LBAS performCorruptRandomLBAs + #define CORRUPT_RANDOM_LBAS_COUNT randomCorruptLBACount + #define CORRUPT_RANDOM_LBAS_VAR \ + bool CORRUPT_RANDOM_LBAS = false;\ + uint16_t CORRUPT_RANDOM_LBAS_COUNT = 0; + #define CORRUPT_RANDOM_LBAS_LONG_OPT_STRING "corruptRandomLBAs" + #define CORRUPT_RANDOM_LBAS_LONG_OPT { CORRUPT_RANDOM_LBAS_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + #define BYTES_TO_CORRUPT_FLAG bytesToCorruptForCorrectableHasBeenEnteredByUser + #define BYTES_TO_CORRUPT_VAL bytesToCorruptForCorrectable + #define BYTES_TO_CORRUPT_VAR \ + bool BYTES_TO_CORRUPT_FLAG = false;\ + uint16_t BYTES_TO_CORRUPT_VAL = 0; + #define BYTES_TO_CORRUPT_LONG_OPT_STRING "bytesToCorrupt" + #define BYTES_TO_CORRUPT_LONG_OPT { BYTES_TO_CORRUPT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } + + //Seagate SCSI/SAS drives only + #define SHOW_SCSI_FW_INFO_FLAG showSCSIFWInfo + #define SHOW_SCSI_FW_INFO_VAR getOptBool SHOW_SCSI_FW_INFO_FLAG = goFalse; + #define SHOW_SCSI_FW_INFO_LONG_OPT_STRING "scsiFWInfo" + #define SHOW_SCSI_FW_INFO_LONG_OPT { SHOW_SCSI_FW_INFO_LONG_OPT_STRING, no_argument, &SHOW_SCSI_FW_INFO_FLAG, goTrue } + + #define LONG_OPT_TERMINATOR { M_NULLPTR, 0, M_NULLPTR, 0 } extern const char *deviceHandleExample; extern const char *deviceHandleName; @@ -2107,7 +2502,7 @@ extern "C" char* get_current_year(char *temp_year); - void openseachest_utility_Info(const char *utilityName, const char *buildVersion, char *seaCPublicVersion); + void openseachest_utility_Info(const char *utilityName, const char *buildVersion, const char *seaCPublicVersion); void utility_Full_Version_Info(const char *utilityName, const char *buildVersion, int seaCPublicMajorVersion, int seaCPublicMinorVersion, int seaCPublicPatchVersion, const char * openseaCommonVersion, const char * openseaOperationVersion); @@ -2421,6 +2816,20 @@ extern "C" //----------------------------------------------------------------------------- void print_Sanitize_Help(bool shortHelp, const char *utilName); + void print_Sanitize_Freeze_Help(bool shortHelp); + + void print_Sanitize_Anti_Freeze_Help(bool shortHelp); + + void print_Sanitize_Overwrite_Passes_Help(bool shortHelp); + + void print_Sanitize_Overwrite_Invert_Help(bool shortHelp); + + void print_Sanitize_AUSE_Help(bool shortHelp); + + void print_Zone_No_Reset_Help(bool shortHelp); + + void print_Sanitize_No_Deallocate_Help(bool shortHelp); + //----------------------------------------------------------------------------- // // print_Writesame_Help() @@ -2495,9 +2904,9 @@ extern "C" // //----------------------------------------------------------------------------- - void print_Progress_Help(bool shortHelp, char* testsTogetProgressFor); + void print_Progress_Help(bool shortHelp, const char* testsTogetProgressFor); - #define TOOL_EXIT_CODE_STRING_MAX_LENGTH 60 //60 characters SHOULD be plenty, but increase this if we do need more characters for the string. Must be NULL terminated. + #define TOOL_EXIT_CODE_STRING_MAX_LENGTH 60 //60 characters SHOULD be plenty, but increase this if we do need more characters for the string. Must be M_NULLPTR terminated. typedef struct _toolSpecificExitCode { int exitCode; @@ -2512,7 +2921,7 @@ extern "C" // // Entry: //! \param numberOfToolSpecificExitCodes - number of exit codes in the list being given - //! \param toolSpecificExitCodeList - pointer to the list of exit codes that are unique to the tool calling this function. Can be NULL if there are not specific exit codes to print + //! \param toolSpecificExitCodeList - pointer to the list of exit codes that are unique to the tool calling this function. Can be M_NULLPTR if there are not specific exit codes to print //! \param toolName - name of the tool the exit codes are being printed for. Must be non-null. // // Exit: @@ -2551,6 +2960,8 @@ extern "C" //----------------------------------------------------------------------------- void print_Short_DST_Help(bool shortHelp); + void print_SMART_Offline_Data_Collection_Help(bool shortHelp); + //----------------------------------------------------------------------------- // // print_Long_DST_Help() @@ -3016,19 +3427,19 @@ extern "C" //----------------------------------------------------------------------------- void print_Test_Unit_Ready_Help(bool shortHelp); - //----------------------------------------------------------------------------- - // - // print_Fast_Discovery_Help() - // - //! \brief Description: This function prints out the short or long help for the fast discovery option - // - // Entry: - //! \param[in] shortUsage = bool used to select when to print short or long help - // - // Exit: - // - //----------------------------------------------------------------------------- - void print_Fast_Discovery_Help(bool shortUsage); + //----------------------------------------------------------------------------- + // + // print_Fast_Discovery_Help() + // + //! \brief Description: This function prints out the short or long help for the fast discovery option + // + // Entry: + //! \param[in] shortUsage = bool used to select when to print short or long help + // + // Exit: + // + //----------------------------------------------------------------------------- + void print_Fast_Discovery_Help(bool shortUsage); void print_Firmware_Download_Help(bool shortHelp); @@ -3214,6 +3625,8 @@ extern "C" void print_Error_In_Cmd_Line_Args(const char * optstring, const char * arg); + void print_Error_In_Cmd_Line_Args_Short_Opt(char opt, const char * arg); + void print_Buffer_Test_Help(bool shortHelp); //Returns 255 when a memory allocation/reallocation error occurs (prints to stderr), 254 when a parameter is missing, zero otherwise. @@ -3438,7 +3851,7 @@ extern "C" void print_No_Time_Limit_Help(bool shortHelp); - void print_No_Banner_Help(bool shortUsage); + void print_No_Banner_Help(bool shortUsage); void print_SAS_Phy_Partial_Help(bool shortHelp); @@ -3520,6 +3933,138 @@ extern "C" void print_DCO_Disable_Features_Help(bool shortHelp); + void print_Capacity_Model_Number_Mapping_Help(bool shortHelp); + + void print_Change_Id_String_Help(bool shortHelp); + + void print_Show_Phy_Event_Counters_Help(bool shortHelp); + + void print_WRV_Help(bool shortHelp); + + void print_Refresh_Filesystems_Help(bool shortHelp); + + void print_Raw_CDB_Length_Help(bool shortHelp); + + void print_Raw_CDB_Help(bool shortHelp); + + void print_Raw_TFR_Command_Help(bool shortHelp); + void print_Raw_TFR_Feature_Help(bool shortHelp); + void print_Raw_TFR_Feature_Ext_Help(bool shortHelp); + void print_Raw_TFR_Feature_Full_Help(bool shortHelp); + void print_Raw_TFR_LBA_Low_Help(bool shortHelp); + void print_Raw_TFR_LBA_Mid_Help(bool shortHelp); + void print_Raw_TFR_LBA_High_Help(bool shortHelp); + void print_Raw_TFR_LBA_Low_Ext_Help(bool shortHelp); + void print_Raw_TFR_LBA_Mid_Ext_Help(bool shortHelp); + void print_Raw_TFR_LBA_High_Ext_Help(bool shortHelp); + void print_Raw_TFR_LBA_Full_Help(bool shortHelp); + void print_Raw_TFR_Device_Head_Help(bool shortHelp); + void print_Raw_TFR_LBA_Mode_Help(bool shortHelp); + void print_Raw_TFR_Sector_Count_Help(bool shortHelp); + void print_Raw_TFR_Sector_Count_Ext_Help(bool shortHelp); + void print_Raw_TFR_Sector_Count_Full_Help(bool shortHelp); + void print_Raw_TFR_Byte_Block_Help(bool shortHelp); + void print_Raw_TFR_Protocol_Help(bool shortHelp); + void print_Raw_TFR_Check_Condition_Help(bool shortHelp); + void print_Raw_TFR_Size_Help(bool shortHelp); + void print_Raw_TFR_XFer_Length_Register_Help(bool shortHelp); + void print_Raw_TFR_ICC_Help(bool shortHelp); + void print_Raw_TFR_AUX1_Help(bool shortHelp); + void print_Raw_TFR_AUX2_Help(bool shortHelp); + void print_Raw_TFR_AUX3_Help(bool shortHelp); + void print_Raw_TFR_AUX4_Help(bool shortHelp); + void print_Raw_TFR_Aux_Full_Help(bool shortHelp); + + void print_Raw_Data_Length_Help(bool shortHelp); + + void print_Raw_Data_Direction_Help(bool shortHelp); + + void print_Raw_Output_File_Help(bool shortHelp); + + void print_Raw_Input_File_Help(bool shortHelp); + + void print_Raw_Timeout_Help(bool shortHelp); + + void print_Raw_Input_File_Offset_Help(bool shortHelp); + + void print_Check_Pending_List_Help(bool shortHelp); + + void print_Check_Grown_List_Help(bool shortHelp); + + void print_Show_Pending_List_Help(bool shortHelp); + + //----------------------------------------------------------------------------- + // + // print_Create_Uncorrectable_Help() + // + //! \brief Description: This function prints out the short or long help for the create Uncorrectable option + // + // Entry: + //! \param[in] shortHelp = bool used to select when to print short or long help + //! + // Exit: + //! \return VOID + // + //----------------------------------------------------------------------------- + void print_Create_Uncorrectable_Help(bool shortHelp); + + void print_Flag_Uncorrectable_Help(bool shortHelp); + + //----------------------------------------------------------------------------- + // + // print_Uncorrectable_Range_Help() + // + //! \brief Description: This function prints out the short or long help for the uncorrectable range option + // + // Entry: + //! \param[in] shortHelp = bool used to select when to print short or long help + //! + // Exit: + //! \return VOID + // + //----------------------------------------------------------------------------- + void print_Uncorrectable_Range_Help(bool shortHelp); + + //----------------------------------------------------------------------------- + // + // print_Random_Uncorrectable_Help() + // + //! \brief Description: This function prints out the short or long help for the random uncorrectables option + // + // Entry: + //! \param[in] shortHelp = bool used to select when to print short or long help + //! + // Exit: + //! \return VOID + // + //----------------------------------------------------------------------------- + void print_Random_Uncorrectable_Help(bool shortHelp); + + //----------------------------------------------------------------------------- + // + // print_Disable_Read_Uncorrectables_Help() + // + //! \brief Description: This function prints out the short or long help for the disable read uncorrectables option + // + // Entry: + //! \param[in] shortHelp = bool used to select when to print short or long help + //! + // Exit: + //! \return VOID + // + //----------------------------------------------------------------------------- + void print_Disable_Read_Uncorrectables_Help(bool shortHelp); + + void print_Corrupt_LBA_Help(bool shortHelp); + + void print_Corrupt_Range_Help(bool shortHelp); + + void print_Bytes_To_Corrupt_Help(bool shortHelp); + + void print_Corrupt_Random_LBAs_Help(bool shortHelp); + + void print_SCSI_FW_Info_Help(bool shortHelp); + #define OUTPUTPATH_PARSE outputPathPtr = optarg; typedef struct _deviceScanFlags @@ -3544,153 +4089,6 @@ extern "C" void get_Scan_Flags(deviceScanFlags *scanFlags, char *optarg); -#define ERASE_RANGE_UTIL_VARS \ - bool eraseRange = false; \ - uint64_t eraseRangeStart = 0; \ - uint64_t eraseRangeEnd = UINT64_MAX;/*set to a maximum value. If it stays this way, we know to correct this to the device's maxLBA later*/ \ - bool eraseForceWrites = false;//this is an option for SSD's in an erase test like eraseRange where we want to force the write commands to the drive instead of using TRIM/Unmap - -#define ERASE_RANGE_SUBOPT_PARSE \ - if (optarg != NULL) \ - { \ - eraseRange = true; \ - int index = optind - 1; \ - char *nextSubOpt = NULL; \ - bool startSet = false; \ - while (index < argc) \ - { \ - nextSubOpt = strdup(argv[index]); \ - if (strncmp("-", nextSubOpt, 1) != 0) \ - { \ - if (strncmp("forceWrites", nextSubOpt, strlen(nextSubOpt)) == 0)\ - { \ - eraseForceWrites = true; \ - } \ - else if (isdigit(nextSubOpt[0]) != 0) \ - { \ - if (startSet == false) \ - { \ - startSet = true; \ - eraseRangeStart = C_CAST(uint64_t, atoll(nextSubOpt)); \ - } \ - else \ - { \ - eraseRangeEnd = C_CAST(uint64_t, atoll(nextSubOpt)); \ - } \ - } \ - } \ - else \ - { \ - break; \ - } \ - index++; \ - } \ - optind = index; \ - } - -#define ERASE_TIME_UTIL_VARS \ -bool eraseTime = false;\ -time_t eraseTimeSeconds = 0;\ -uint64_t eraseTimeStartLBA = 0; - -#define ERASE_TIME_SUBOPT_PARSE \ - if (optarg != NULL) \ - { \ - eraseTime = true; \ - int index = optind - 1; \ - char *nextSubOpt = NULL; \ - bool lbaSet = false; \ - uint64_t timeMultiplier = 1;/*use this if the user enters hours or minutes to increment the erase time*/ \ - while (index < argc) \ - { \ - nextSubOpt = strdup(argv[index]); /*get the next subopt*/ \ - if (strncmp("-", nextSubOpt, 1) != 0)/*check if optarg is next switch so that we break out of parsing suboptions*/ \ - { \ - if (strncmp("minutes", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - timeMultiplier = 60; \ - } \ - else if (strncmp("hours", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - timeMultiplier = 3600; \ - } \ - else if (strncmp("days", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - timeMultiplier = 86400; \ - } \ - else if (isdigit(nextSubOpt[0]) != 0)/*this is an LBA*/ \ - { \ - if (lbaSet == false) \ - { \ - lbaSet = true; \ - eraseTimeStartLBA = C_CAST(uint64_t, atoll(nextSubOpt)); \ - } \ - else \ - { \ - eraseTimeSeconds = C_CAST(uint64_t, atoll(nextSubOpt)); \ - } \ - } \ - } \ - else \ - { \ - break; \ - } \ - index++; \ - } \ - optind = index; /*reset this since we were searching for options to pull out around getopt*/ \ - eraseTimeSeconds *= timeMultiplier;/*adjust to a time in seconds if something other than seconds were entered*/ \ - } - -#define SANITIZE_SUBOPT_PARSE \ -if (optarg != NULL) \ -{ \ - int index = optind - 1; \ - char *nextSubOpt = NULL; \ - while (index < argc) \ - { \ - nextSubOpt = strdup(argv[index]); /*get the next subopt*/ \ - if (strncmp("-", nextSubOpt, 1) != 0) /*check if optarg is next switch so that we break out of parsing suboptions*/ \ - { \ - if (strncmp("blockerase", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - sanitize = true; \ - sanblockErase = true; \ - } \ - else if (strncmp("cryptoerase", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - sanitize = true; \ - sancryptoErase = true; \ - } \ - else if (strncmp("overwrite", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - sanitize = true; \ - sanoverwrite = true; \ - } \ - else if (strncmp("freezelock", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - sanitize = true; \ - sanfreezelock = true; \ - } \ - else if (strncmp("antifreezelock", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - sanitize = true; \ - sanAntiFreezeLock = true; \ - } \ - else if (strncmp("info", nextSubOpt, strlen(nextSubOpt)) == 0) \ - { \ - sanitize = true; /*this flag is used to show the support sanitize commands*/ \ - sanitizeInfo = true; \ - } \ - } \ - else \ - { \ - break; \ - } \ - index++; \ - } \ - optind = index; /*reset this since we were searching for options to pull out around getopt*/ \ -} - #if defined (__cplusplus) } #endif diff --git a/meson.build b/meson.build index 8382232b..e774146d 100644 --- a/meson.build +++ b/meson.build @@ -1,35 +1,108 @@ -project('openSeaChest', 'c', license: 'MPL-2.0', default_options : ['warning_level=2']) +# SPDX-License-Identifier: MPL-2.0 +project('openSeaChest', 'c', license: 'MPL-2.0', default_options : ['warning_level=2', 'b_pie=true']) c = meson.get_compiler('c') - warning_flags = [ ] +linker_flags = [ ] #additional linker flags to add per-compiler for hardening. if c.get_id().contains('gcc') or c.get_id().contains('clang') #TODO: Add -Wcast-align=strict and fix these issues to help ensure better portability #NOTE: -Wsign-conversion can be useful while debugging, but there are numerous places this shows up # and it is not useful, so only add it while debugging. + #NOTE: 4/4/2024 - adding flags from https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++ warning_flags = [ # '-Wcast-align=strict', - # '-Wsign-conversion', - '-Wshadow=compatible-local', - '-Wvla', - '-Wfloat-equal', - '-Wnull-dereference', - '-Wunused-const-variable', - '-Wduplicated-cond', - '-Wjump-misses-init', - '-Wstringop-overflow', - '-Wlogical-op', - '-Wshift-overflow=2', - '-Wdouble-promotion', - '-Wformat-security', + '-Wshadow=compatible-local', + '-Wvla', + '-Wfloat-equal', + '-Wnull-dereference', + '-Wunused-const-variable', + '-Wunused-parameter', + '-Wunused-value', + '-Wduplicated-cond', + '-Wjump-misses-init', + '-Wstringop-overflow', + '-Wlogical-op', + '-Wshift-overflow', + '-Wshift-overflow=1', + '-Wshift-overflow=2', + '-Wdouble-promotion', + '-Wformat-security', '-Wold-style-definition', '-Wstrict-prototypes', '-Wmissing-declarations', '-Wmissing-prototypes', '-Wchar-subscripts', - '-Wundef' + '-Wundef', + '-Wformat', + '-Wformat=2', + '-Wsign-conversion', + '-Wint-conversion',#-Warith-conversion + '-Wenum-conversion', + '-Wfloat-conversion', + '-Wint-to-pointer-cast', + '-Wimplicit-fallthrough', + '-D_GLIBCXX_ASSERTIONS', + '-fstrict-flex-arrays=1', #NOTE: Using level 1 since Windows often uses [1] at the end of it's structures. opensea-*libs has used this in a few places too. + '-fstack-protector-strong', + '-fno-delete-null-pointer-checks', + '-fno-strict-overflow', + '-fno-strict-aliasing', + '-ftrivial-auto-var-init=zero', + '-Wtrampolines', #GCC only at this time + '-Werror=implicit', + '-Werror=incompatible-pointer-types', + '-Wincompatible-pointer-types-discards-qualifiers', + '-Werror=int-conversion', + '-Werror=implicit-int', + '-Woverlength-strings', + '-Wnewline-eof', + '-Wno-c23-extensions', #We do not want this warning since we are already checking for when C23 extensions are available before we use them. If not, we use a compiler specific definition, or make it an empty definition. + '-Wparentheses', + '-Wextra-semi', + '-Wcast-qual', + '-Werror=sometimes-uninitialized', + '-Wuninitialized', + '-Wunevaluated-expression', + '-Wunsequenced', + '-Wvarargs', + '-Wwrite-strings', + '-Wrestrict', + '-Wstringop-truncation', + '-Werror=trigraphs', + '-Wunreachable-code', + '-Wcomment', + '-Wsequence-point', + '-Wreturn-type', + '-fvisibility=hidden', #to work similarly to Window's DLL import/export + ] + + if c.get_id().contains('gcc') and target_machine.system() == 'windows' + #According to the link below, this is not needed in Windows...it also causes a bug in some versions of GCC for Windows. + #https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 + #NOTE: While this appears to be fixed for versions 11 and 12, the current CI is failing on this with + # version 12.2. If we want to or need to enable this, it should be done based on which versions we + # know have been patched for this. -TJE + else + warning_flags += '-fstack-clash-protection' + endif + + if target_machine.cpu_family() == 'ppc64' + #power pc builds generate a lot of warnings/notes about ABI changes since GCC-5 + #this flag is disabling them because this is way too noisy. + warning_flags += ['-Wno-psabi'] + elif target_machine.cpu_family() == 'x86_64' + warning_flags += ['-fcf-protection=full'] #this may be linux only at this time. + elif target_machine.cpu_family() == 'aarch64' + warning_flags += ['-mbranch-protection=standard'] + endif + + linker_flags += [ + '-Wl,-z,nodlopen', + '-Wl,-z,noexecstack', + '-Wl,-z,relro', + '-Wl,-z,now' ] elif c.get_id().contains('msvc') #See here for enabling/disabling msvc warnings: @@ -43,13 +116,11 @@ elif c.get_id().contains('msvc') '/wd4668', # 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'. While like -Wundef, this creates too many warnings in system headers to use '/wd4820', # 'bytes' bytes padding added after construct 'member_name' '/wd4710', # 'function' : function not inlined - #'/wd4255', # 'function' : no function prototype given: converting '()' to '(void)' #NOTE: Only needed for /Wall, otherwise enabling can be good-TJE '/wd5045', # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified '/wd4711', # function 'function' selected for inline expansion '/wd4324', # 'struct_name' : structure was padded due to __declspec(align()) '/wd4221', # nonstandard extension used : 'identifier' : cannot be initialized using address of automatic variable '/wd4204', # nonstandard extension used : non-constant aggregate initializer - '/wd4061', # enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label '/wd5105', # macro expansion producing 'defined' has undefined behavior '/wd4746', # volatile access of '<expression>' is subject to /volatile:[iso|ms] setting; consider using __iso_volatile_load/store intrinsic functions. #Turn on the following warnings to make the output more useful or like GCC/clang @@ -60,30 +131,74 @@ elif c.get_id().contains('msvc') '/w15031', # #pragma warning(pop): likely mismatch, popping warning state pushed in different file '/w15032', # detected #pragma warning(push) with no corresponding #pragma warning(pop) '/w15262', # implicit fall-through occurs here; are you missing a break statement? Use [[fallthrough]] when a break statement is intentionally omitted between cases + '/w14255', # 'function' : no function prototype given: converting '()' to '(void)' #NOTE: Only needed for /Wall, otherwise enabling can be good-TJE + '/w14242', # identifier conversion from type 1 to type 2, possible loss of data (matches -wconversion above) + '/w14254', # operator conversion from type 1 to type 2, possible loss of data (matches -wconversion above) + '/w14287', # operator: unsigned/negative constant mismatch (matches -wconversion above) + '/w14296', # operator: expression is always false + '/w14365', # action: conversion from type 1 to type 2, signed/unsigned mismatch (matches -wconversion above) + '/w14388', # implicit conversion warning during a comparison (matches -wconversion above) + '/w14545', # expression before comma evaluates to a function which is missing an argument list + '/w14546', # function call before comma missing argument list + '/w14547', # 'operator' : operator before comma has no effect; expected operator with side-effect + '/w14548', # expression before comma has no effect; expected expression with side-effect + '/w14549', # 'operator1': operator before comma has no effect; did you intend 'operator2'? + '/w14574', # 'identifier' is defined to be '0': did you mean to use '#if identifier'? + '/w14605', # '/Dmacro' specified on current command line, but was not specified when precompiled header was built + '/w14555', # expression has no effect; expected expression with side-effect + '/w14774', # 'string' : format string expected in argument number is not a string literal + '/w14777', # 'function' : format string 'string' requires an argument of type 'type1', but variadic argument number has type 'type2' + '/w14826', # Conversion from 'type1' to 'type2' is sign-extended. This may cause unexpected runtime behavior (more -wconversion) + '/w15219', # implicit conversion from 'type-1' to 'type-2', possible loss of data (-wconversion) + '/w15240', # 'attribute-name': attribute is ignored in this syntactic position + '/w15245', # 'function': unreferenced function with internal linkage has been removed + '/w14555', # expression has no effect; expected expression with side-effect + '/w15264', # 'variable-name': 'const' variable is not used + '/w24302', # 'conversion': truncation from 'type1' to 'type2' + '/w14311', # 'variable': pointer truncation from 'type' to 'type' + '/w14312', # 'operation': conversion from 'type1' to 'type2' of greater size + '/w14319', # 'operator': zero extending 'type1' to 'type2' of greater size #Treat the following as errors + '/we4431', # missing type specifier - int assumed. Note: C no longer supports default-int + '/we4905', # wide string literal cast to 'LPSTR' + '/we4906', # string literal cast to 'LPWSTR' '/we4837', # trigraph detected: '??character' replaced by 'character' '/we4628', # digraphs not supported with -Ze. Character sequence 'digraph' not interpreted as alternate token for 'char' '/we4289', # nonstandard extension used : 'var' : loop control variable declared in the for-loop is used outside the for-loop scope + '/we4464', # relative include path contains '..' + '/std:c17', #NOTE: It would be better to specify for the project settings above for all compilers, but currently still supporting MSVC and GCC compilers that may not be C11 compatible.-TJE + '/GS', #security cookie for stack protection + '/sdl', #adds recommended security development lifecycle checks + '/Qspectre', + '/guard:cf', #control flow guard + '/d2guard4', #control flow guard + ] + + linker_flags += [ + '/guard:cf', #control flow guard + '/SafeSEH', #on by default in x64 so it is unrecognized otherwise. + '/NXCOMPAT', #data execution prevention + '/dynamicbase', #address space randomization ] - #TODO: check compiler version to handle warnings that were off by default in earlier versions - #ex: C4431 (level 4) missing type specifier - int assumed. Note: C no longer supports default-int - # This was off by default in compilers before VS2012. elif c.get_id().contains('xlc') #This section is for IBM's xlc compiler and warning options it may need. #NOTE: xlcclang should be handled above #See following links: + #https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=reference-individual-xl-compiler-option-descriptions #https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=reference-supported-xl-compiler-options-by-different-invocations #https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=end-mapping-legacy-xl-compiler-options-gcc-options #https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=reference-individual-xl-compiler-option-descriptions + #https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=descriptions-qlanglvl-std warning_flags = [] endif add_project_arguments(c.get_supported_arguments(warning_flags), language : 'c') +add_project_link_arguments(c.get_supported_link_arguments(linker_flags), language : 'c') small_code_cc_flags = [] small_code_link_flags = [] -if (c.get_id() == 'gcc' or c.get_id() == 'clang') +if (c.get_id() == 'gcc' or c.get_id() == 'clang') and target_machine.system() != 'windows' small_code_cc_flags = [ '-ffunction-sections', @@ -147,6 +262,16 @@ if target_machine.system() == 'windows' add_project_arguments('-D_CRT_SECURE_NO_WARNINGS', language : 'c') endif +usehelp2man = false +if target_machine.system() != 'windows' + if meson.can_run_host_binaries() + help2man = find_program('help2man', required : false) + if help2man.found() + usehelp2man = true + endif + endif +endif + opensea_common = subproject('opensea-common') opensea_common_dep = opensea_common.get_variable('opensea_common_dep') @@ -159,11 +284,17 @@ opensea_operations_dep = opensea_operations.get_variable('opensea_operations_dep incdir = include_directories('include') exe_src_map = { - 'Format': 'Format' + #This exists to allow mapping an exe from a specific filename to a different output name. + #the openSeaChest_Format tool was called openSeaChest_FormatUnit before NVMe was added and needed this map for a while. + #This is no longer needed at this time, but may end up used in the future as more utilities are migrated to openSeaChest } foreach p : get_option('tools') executable('openSeaChest_' + p, common_sources, 'utils/C/openSeaChest/openSeaChest_' + exe_src_map.get(p, p) + '.c', dependencies : [opensea_common_dep, opensea_transport_dep, opensea_operations_dep, os_deps], include_directories : incdir, install : true) + if usehelp2man + #use help2man to generate manpages before installing them + run_command(help2man, '-o', meson.project_source_root() + '/docs/man/man8/openSeaChest_' + exe_src_map.get(p, p) + '.8', meson.project_build_root() + '/openSeaChest_' + exe_src_map.get(p, p), check: false) + endif install_man('docs/man/man8/openSeaChest_' + exe_src_map.get(p, p) + '.8') endforeach install_man('docs/man/man8/openSeaChest.8') diff --git a/meson_crosscompile/Windows-Clang.txt b/meson_crosscompile/Windows-Clang.txt new file mode 100644 index 00000000..3db369ef --- /dev/null +++ b/meson_crosscompile/Windows-Clang.txt @@ -0,0 +1,33 @@ +#See https://mesonbuild.com/Cross-compilation.html +#and https://mesonbuild.com/Machine-files.html +#and https://mesonbuild.com/Reference-tables.html#cpu-families +#example usage of this file: +# meson setup --buildtype=release --native-file=./meson_crosscompile/Windows-Clang.txt nativebuild_win_clang +# ninja -C nativebuild_win_clang + +#NOTE: This is for the LLVM.exe installer from github. + +[binaries] +c = 'clang.exe' +cpp = 'clang++.exe' +ar = 'llvm-ar.exe' +c_ld = 'lld-link.exe' +cpp_ld = 'lld-link.exe' +strip = 'llvm-strip.exe' +windres = 'llvm-rc.exe' +llvm-config = 'llvm-config.exe' + +[properties] +has_function_printf = true + +[host_machine] +system = 'windows' +subsystem = 'windows' +kernel = 'nt' +endian = 'little' +cpu_family = 'x86_64' +cpu = '' + +[built-in options] +default_library='static' +b_pie='false' \ No newline at end of file diff --git a/meson_crosscompile/msvc_arm64.txt b/meson_crosscompile/msvc_arm64.txt new file mode 100644 index 00000000..b746bb93 --- /dev/null +++ b/meson_crosscompile/msvc_arm64.txt @@ -0,0 +1,30 @@ +#See https://mesonbuild.com/Cross-compilation.html +#and https://mesonbuild.com/Machine-files.html +#and https://mesonbuild.com/Reference-tables.html#cpu-families +#example usage of this file: +# meson setup --buildtype=release --cross-file=./meson_crosscompile/msvc_arm64.txt crossbuild_msvc_arm64 +# ninja -C crossbuild_msvc_arm64 + +#NOTE: You must execute the vcvarsamd64_arm64.bat to set this environment up first. This is essentially the +# setup for the developer command prompt for cross-tool compiling to arm64. + +[binaries] +c = 'cl.exe' +ld = 'link.exe' +strip = 'strip' + +[properties] +has_function_printf = true +skip_sanity_check = true + +[host_machine] +system = 'windows' +subsystem = 'windows' +kernel = 'nt' +cpu_family = 'aarch64' +cpu = 'armv8' +endian = 'little' + +[built-in options] +default_library='static' + diff --git a/meson_options.txt b/meson_options.txt index 3e641704..992c5374 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,6 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 option('tools', type : 'array', choices : [ 'Basics', 'Configure', + 'Defect', 'Erase', 'Firmware', 'Format', @@ -10,6 +12,7 @@ option('tools', type : 'array', choices : [ 'NVMe', 'PassthroughTest', 'PowerControl', + 'Raw', 'Reservations', 'Security', 'SMART', diff --git a/nfpm.yaml b/nfpm.yaml index 7a3b3ed8..300fd70e 100644 --- a/nfpm.yaml +++ b/nfpm.yaml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 name: "openseachest" arch: "amd64" platform: "linux" @@ -14,9 +15,9 @@ homepage: "https://www.github.com/Seagate/openSeaChest" license: "MPL" contents: - src: openSeaChest_* - dst: /usr/bin/openSeaChest + dst: /usr/local/bin/openSeaChest file_info: # Make sure that the mode is specified in octal, e.g. 0644 instead of 644. mode: 0755 - src: man/man8/openSeaChest_*.8 - dst: /usr/bin/openSeaChest/man/man8/ + dst: /usr/local/share/man/man8/ diff --git a/src/EULA.c b/src/EULA.c index cf7bae5f..ef819702 100644 --- a/src/EULA.c +++ b/src/EULA.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2018 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -760,7 +761,7 @@ void print_Open_Source_Licenses(void) #endif #endif #elif defined (__sun) || defined (_AIX) - //TODO: Any special license for system libc/etc that needs to be shown. Cannot easily identify one at this time - TJE + //Any special license for system libc/etc that needs to be shown. Cannot easily identify one at this time - TJE #else #error Please update #if for system library licenses! #endif diff --git a/src/openseachest_util_options.c b/src/openseachest_util_options.c index 7fa1b26a..f5973def 100644 --- a/src/openseachest_util_options.c +++ b/src/openseachest_util_options.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -12,6 +13,13 @@ // \file openseachest_util_options.c // \brief This file defines the functions and macros to make building a utility easier. +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "time_utils.h" +#include "io_utils.h" +#include "string_utils.h" + #include "openseachest_util_options.h" #if defined (__linux__) @@ -29,6 +37,7 @@ const char *deviceHandleExample = "/dev/da<#>"; const char *deviceHandleName = "<da_device>"; const char *commandWindowType = "shell"; #elif defined (_WIN32) +#include "windows_version_detect.h" const char *deviceHandleExample = "PD<#>"; const char *deviceHandleName = "<physical_device>"; const char *commandWindowType = "command"; @@ -63,6 +72,22 @@ void print_Bug_Report_Email(bool shortHelp) } } +M_NODISCARD bool set_Verbosity_From_String(const char* requestedLevel, eVerbosityLevels* verbosity) +{ + bool set = false; + if (requestedLevel && verbosity) + { + char* end = M_NULLPTR; + long temp = strtol(requestedLevel, &end, 10); + if (!(temp == LONG_MAX && errno == ERANGE) && !(temp == 0 && requestedLevel == end) && strcmp(end, "") == 0 && C_CAST(eVerbosityLevels, temp) < VERBOSITY_MAX) + { + *verbosity = C_CAST(eVerbosityLevels, temp); + set = true; + } + } + return set; +} + void print_Elevated_Privileges_Text(void) { printf("WARNING: You must run with elevated privileges to communicate with devices in the system."); @@ -74,8 +99,8 @@ void print_Elevated_Privileges_Text(void) printf("(admin, root, sudo, etc)"); printf("\nor be part of a privileged group with disk access."); #if defined (__linux__) - printf("(disk)"); -//TODO: If other systems have groups which get disk access, list them here. Currently only know about the disk group in Linux + printf("(disk)"); +//If other systems have groups which get disk access, list them here. Currently only know about the disk group in Linux #endif #endif @@ -83,7 +108,7 @@ void print_Elevated_Privileges_Text(void) #if defined (_WIN32) printf("In Windows, open the Command Prompt using \"Run as administrator\".\n"); #elif defined (__unix__) || defined(__APPLE__) - //TODO: handle the various linux/unix/unix-like OSs with more ifdefs here + //handle the various linux/unix/unix-like OSs with more ifdefs here #if defined (__linux__) #if defined (VMK_CROSS_COMP) printf("In ESXi, put sudo before the command. This may require inputting your login password.\n"); @@ -98,7 +123,7 @@ void print_Elevated_Privileges_Text(void) #elif defined (__sun) printf("In Solaris, put sudo before the command. This may require inputting your login password.\n"); printf("In Solaris, log in to a root terminal (su), then execute the command. This requires the root password.\n"); -#else //generic unix/unix-like case //TODO: Add more OS specific ifdefs to customize messages above +#else //generic unix/unix-like case //Add more OS specific ifdefs to customize messages above printf("In Linux/Unix, put sudo before the command. This may require inputting your login password.\n"); printf("In Linux/Unix, log in to a root terminal (su), then execute the command. This requires the root password.\n"); #endif @@ -112,7 +137,7 @@ void print_Elevated_Privileges_Text(void) char* get_current_year(char *temp_year) { - size_t len = strlen(__DATE__); + size_t len = safe_strlen(__DATE__); temp_year[4] = '\0'; temp_year[3] = __DATE__[len - 1]; temp_year[2] = __DATE__[len - 2]; @@ -121,24 +146,18 @@ char* get_current_year(char *temp_year) return temp_year; } -#include "common.h" -#include "common_platform.h" +#include "common_types.h" -void openseachest_utility_Info(const char *utilityName, const char *buildVersion, char *seaCPublicVersion) +void openseachest_utility_Info(const char *utilityName, const char *buildVersion, const char *seaCPublicVersion) { eArchitecture architecture = get_Compiled_Architecture(); - time_t g_curTime = time(NULL); - char *year = calloc(CURRENT_YEAR_LENGTH, sizeof(char)); - char *userName = NULL; -#define CURRENT_TIME_STRING_MAX_LENGTH 30 - char currentTime[CURRENT_TIME_STRING_MAX_LENGTH] = { 0 }; - struct tm utilTime; - memset(&utilTime, 0, sizeof(struct tm)); + char *year = safe_calloc(CURRENT_YEAR_LENGTH, sizeof(char)); + char *userName = M_NULLPTR; #if defined (ENABLE_READ_USERNAME) if (SUCCESS != get_Current_User_Name(&userName)) { #define UNKNOWN_USER_NAME_MAX_LENGTH 36 - userName = C_CAST(char*, calloc(UNKNOWN_USER_NAME_MAX_LENGTH, sizeof(char))); + userName = C_CAST(char*, safe_calloc(UNKNOWN_USER_NAME_MAX_LENGTH, sizeof(char))); if (userName) { snprintf(userName, UNKNOWN_USER_NAME_MAX_LENGTH, "Unable to retrieve current username"); @@ -158,7 +177,7 @@ void openseachest_utility_Info(const char *utilityName, const char *buildVersion userName = strdup("current user"); } #endif //ENABLE_READ_USERNAME - //char g_timeString[64] = { 0 }; + //DECLARE_ZERO_INIT_ARRAY(char, g_timeString, 64); printf("==========================================================================================\n"); printf(" %s - openSeaChest drive utilities", utilityName); printf(" - NVMe Enabled"); @@ -167,19 +186,19 @@ void openseachest_utility_Info(const char *utilityName, const char *buildVersion print_Architecture(architecture); printf("\n"); printf(" Build Date: %s\n", __DATE__); - if (0 == strftime(currentTime, CURRENT_TIME_STRING_MAX_LENGTH, "%c", get_Localtime(&g_curTime, &utilTime))) + if (get_current_timestamp() == false) { - snprintf(currentTime, CURRENT_TIME_STRING_MAX_LENGTH, "Unable to get local time"); + snprintf(CURRENT_TIME_STRING, CURRENT_TIME_STRING_LENGTH, "Unable to get local time"); } - printf(" Today: %s\tUser: %s\n", currentTime, userName); + printf(" Today: %s\tUser: %s\n", CURRENT_TIME_STRING, userName); printf("==========================================================================================\n"); - safe_Free(userName) - safe_Free(year) + safe_free(&userName); + safe_free(&year); } void utility_Full_Version_Info(const char *utilityName, const char *buildVersion, int seaCPublicMajorVersion, int seaCPublicMinorVersion, int seaCPublicPatchVersion, const char * openseaCommonVersion, const char * openseaOperationVersion) { - char osName[OS_NAME_SIZE] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, osName, OS_NAME_SIZE); OSVersionNumber osversionnumber; eCompiler compilerUsed = OPENSEA_COMPILER_UNKNOWN; compilerVersion compilerVersionInfo; @@ -191,7 +210,7 @@ void utility_Full_Version_Info(const char *utilityName, const char *buildVersion printf("Version Info for %s:\n", utilityName); printf("\tUtility Version: %s\n", buildVersion); printf("\topensea-common Version: %s\n", openseaCommonVersion); - printf("\topensea-transport Version: %" PRId32".%" PRId32".%" PRId32"\n", seaCPublicMajorVersion, seaCPublicMinorVersion, seaCPublicPatchVersion); + printf("\topensea-transport Version: %" PRId32 ".%" PRId32 ".%" PRId32 "\n", seaCPublicMajorVersion, seaCPublicMinorVersion, seaCPublicPatchVersion); printf("\topensea-operations Version: %s\n", openseaOperationVersion); printf("\tBuild Date: %s\n", __DATE__); printf("\tCompiled Architecture: "); @@ -209,9 +228,16 @@ void utility_Full_Version_Info(const char *utilityName, const char *buildVersion printf("\n\tOperating System Name: %s\n", osName); } +//This function is used in at_exit() only. +//It will flush stdout and stderr after printing one final newline character. void print_Final_newline(void) { printf("\n"); + //Flushing stdout and stderr + //https://wiki.sei.cmu.edu/confluence/display/c/FIO23-C.+Do+not+exit+with+unflushed+data+in+stdout+or+stderr + //NOTE: Links shows checking for EOF for an error....this is at an exit...I have no idea what error handling we would want at this point. + fflush(stdout); + fflush(stderr); } void print_SeaChest_Util_Exit_Codes(int numberOfToolSpecificExitCodes, ptrToolSpecificxitCode toolSpecificExitCodeList, const char * toolName) @@ -227,7 +253,7 @@ void print_SeaChest_Util_Exit_Codes(int numberOfToolSpecificExitCodes, ptrToolSp printf("\t%d = Cannot Open File\n", UTIL_EXIT_CANNOT_OPEN_FILE); printf("\t%d = File Already Exists\n", UTIL_EXIT_FILE_ALREADY_EXISTS); printf("\t%d = Need Elevated Privileges\n", UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); - //TODO: more generic exit code help above this comment. Tool specific exit codes in if statement below + //more generic exit code help above this comment. Tool specific exit codes in if statement below if (numberOfToolSpecificExitCodes > 0 && toolSpecificExitCodeList) { printf("\t---%s specific exit codes---\n", toolName); @@ -242,55 +268,55 @@ void print_SeaChest_Util_Exit_Codes(int numberOfToolSpecificExitCodes, ptrToolSp void get_Scan_Flags(deviceScanFlags *scanFlags, char *optarg) { - if(strncmp("ata", optarg, strlen(optarg)) == 0) + if(strncmp("ata", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanATA = true; } - else if (strlen(optarg) == 3 && strncmp("usb", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 3 && strncmp("usb", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanUSB = true; } - else if (strlen(optarg) == 4 && strncmp("scsi", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 4 && strncmp("scsi", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanSCSI = true; } - else if (strlen(optarg) == 4 && strncmp("nvme", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 4 && strncmp("nvme", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanNVMe = true; } - else if (strlen(optarg) == 4 && strncmp("raid", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 4 && strncmp("raid", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanRAID = true; } - else if (strlen(optarg) == 12 && strncmp("interfaceATA", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 12 && strncmp("interfaceATA", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanInterfaceATA = true; } - else if (strlen(optarg) == 12 && strncmp("interfaceUSB", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 12 && strncmp("interfaceUSB", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanInterfaceUSB = true; } - else if (strlen(optarg) == 13 && strncmp("interfaceSCSI", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 13 && strncmp("interfaceSCSI", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanInterfaceSCSI = true; } - else if (strlen(optarg) == 13 && strncmp("interfaceNVME", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 13 && strncmp("interfaceNVME", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanInterfaceNVMe = true; } - else if (strlen(optarg) == 2 && strncmp("sd", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 2 && strncmp("sd", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanSD = true; } - else if (strlen(optarg) == 6 && strncmp("sgtosd", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 6 && strncmp("sgtosd", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanSDandSG = true; } - else if (strlen(optarg) == 10 && strncmp("ignoreCSMI", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 10 && strncmp("ignoreCSMI", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanIgnoreCSMI = true; } - else if (strlen(optarg) == 15 && strncmp("allowDuplicates", optarg, strlen(optarg)) == 0) + else if (safe_strlen(optarg) == 15 && strncmp("allowDuplicates", optarg, safe_strlen(optarg)) == 0) { scanFlags->scanAllowDuplicateDevices = true; } @@ -516,6 +542,32 @@ void print_Erase_Time_Help(bool shortHelp) } } +void print_Sanitize_Freeze_Help(bool shortHelp) +{ + printf("\t--%s\t(SATA Only)\n", SANITIZE_FREEZE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tFreezelock is a command to block processing of sanitize\n"); + printf("\t\toperations until a power cycle is performed on a device.\n"); + printf("\t\tIt is only available on ATA drives. Once this command has been\n"); + printf("\t\tsent, the freezelock status becomes immediate and cannot be\n"); + printf("\t\tcleared until the drive has been powered off. All sanitize\n"); + printf("\t\tcommands, except a sanitize status will be aborted.\n\n"); + } +} + +void print_Sanitize_Anti_Freeze_Help(bool shortHelp) +{ + printf("\t--%s\t(SATA Only)\n", SANITIZE_ANTIFREEZE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tAntifreezelock is a command that is designed to block a\n"); + printf("\t\tfreezelock command from locking out the sanitize feature set.\n"); + printf("\t\tIt is only available on ATA drives that support the ACS3, or\n"); + printf("\t\tnewer specification.\n\n"); + } +} + void print_Sanitize_Help(bool shortHelp, const char *utilName) { printf("\t--%s [info | blockerase | cryptoerase |\n", SANITIZE_LONG_OPT_STRING); @@ -530,10 +582,31 @@ void print_Sanitize_Help(bool shortHelp, const char *utilName) printf("\t\tsanitize erase operations are persistent across a power cycle\n"); printf("\t\tand cannot be stopped\n"); printf("\t\tExample: --%s blockerase --%s\n\n", SANITIZE_LONG_OPT_STRING, POLL_LONG_OPT_STRING); -#if defined (_WIN32)//TODO: handle Win PE somehow when we support WinPE - printf("\t\tNote: Windows 8 and higher block sanitize commands. Sanitize\n"); - printf("\t\toperations will show a failure status on these systems.\n\n"); -#endif + printf("\t\tBy default, sanitize runs in restricted exit mode, meaning the\n"); + printf("\t\tonly way to exit a failed sanitize is to attempt sanitize again\n"); + printf("\t\tuntil it completes successfully. Add the --%s option to run\n", SANITIZE_AUSE_LONG_OPT_STRING); + printf("\t\tin unrestricted mode. In unrestricted mode, if sanitize fails\n"); + printf("\t\tyou can exit this mode with the \"exit failure mode\" command\n"); + printf("\t\tor a successful sanitize command.\n\n"); + printf("\t\tFor Zoned block devices, the --%s option can be used\n", ZONE_NO_RESET_LONG_OPT_STRING); + printf("\t\tto stop the write pointers from resetting allowing full\n"); + printf("\t\tdrive verification to be performed upon completion of sanitize\n"); + printf("\t\tFor NVMe devices that support the deallocate feature (TRIM), the\n"); + printf("\t\t--%s option can be used to prevent the deallocation of blocks at\n", NO_DEALLOCATE_AFTER_ERASE_LONG_OPT_STRING); + printf("\t\tcompletion of sanitize to allow for full drive verification.\n"); + printf("\t\tNOTE: An NVMe controller may inhibit the no deallocate behavior\n"); + printf("\t\t and may deallocate anyways or fail the sanitize command when\n"); + printf("\t\t no deallocate is specified.\n\n"); +#if defined (_WIN32) + if (!is_Windows_PE()) + { + printf("\t\tNote: Windows 8 and higher block sanitize commands. Sanitize\n"); + printf("\t\toperations will show a failure status on these systems.\n"); + printf("\t\tStarting in Windows 11 or Windows 10 21H1, sanitize crypto\n"); + printf("\t\tor block erase can be executed on NVMe data drives that\n"); + printf("\t\tsupport the sanitize command set.\n\n"); + } +#endif //_WIN32 //blockerase info printf("\t\t* blockerase on some solid state drives is very fast at less\n"); printf("\t\tthan one (1) second, while others may take more that 30 seconds\n"); @@ -546,26 +619,116 @@ void print_Sanitize_Help(bool shortHelp, const char *utilName) printf("\t\tdata causing all previous data to be useless.\n\n"); //overwrite info printf("\t\t* overwrite is a physical overwrite on all current, past, and\n"); - printf("\t\tpotential user data. The ATA and SCSI specifications allow a\n"); + printf("\t\tpotential user data. The ATA, NVMe, & SCSI specifications allow a\n"); printf("\t\tuser defined pattern and multiple passes. %s will\n", utilName); - printf("\t\tuse a zero pattern and a single pass for this operation.\n\n"); + printf("\t\tuse a zero pattern and a single pass for this operation\n"); + printf("\t\tby default. Use --%s and --%s to specify\n", SANITIZE_OVERWRITE_PASSES_LONG_OPT_STRING, SANITIZE_IPBP_LONG_OPT_STRING); + printf("\t\tthe number of passes and whether to invert the pattern between\n"); + printf("\t\teach overwrite pass.\n\n"); //freezelock info - printf("\t\t* freezelock is a command to block processing of sanitize\n"); - printf("\t\toperations until a power cycle is performed on a device.\n"); - printf("\t\tIt is only available on ATA drives. Once this command has been\n"); - printf("\t\tsent, the freezelock status becomes immediate and cannot be\n"); - printf("\t\tcleared until the drive has been powered off. All sanitize\n"); - printf("\t\tcommands, except a sanitize status will be aborted.\n\n"); + printf("\t\t* freezelock - migrate to use of --%s\n\n", SANITIZE_FREEZE_LONG_OPT_STRING); //anti freezlock info - printf("\t\t* antifreezelock is a command that is designed to block a\n"); - printf("\t\tfreezelock command from locking out the sanitize feature set.\n"); - printf("\t\tIt is only available on ATA drives that support the ACS3, or\n"); - printf("\t\tnewer specification.\n\n"); + printf("\t\t* antifreezelock - migrate to use of --%s\n\n", SANITIZE_ANTIFREEZE_LONG_OPT_STRING); printf("\t\tWARNING: Sanitize may affect all LUNs/namespaces for devices\n"); printf("\t\t with multiple logical units or namespaces.\n\n"); } } +void print_Sanitize_Overwrite_Passes_Help(bool shortHelp) +{ + printf("\t--%s [ number of overwrite passes ]\n", SANITIZE_OVERWRITE_PASSES_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tSpecify the number of overwrite passes to use during a sanitize\n"); + printf("\t\toverwrite operation. By default, only a single overwrite pass\n"); + printf("\t\tis used unless this option specifies a different value.\n"); + printf("\t\tThe maximum number of passes varies by drive type:\n"); + printf("\t\tATA: 16 passes\n"); + printf("\t\tNVMe: 16 passes\n"); + printf("\t\tSCSI: 31 passes\n"); + printf("\t\tUse the --%s option to instruct the device to invert\n", SANITIZE_IPBP_LONG_OPT_STRING); + printf("\t\tthe pattern between each overwrite pass.\n"); + printf("\n"); + } +} + +void print_Sanitize_Overwrite_Invert_Help(bool shortHelp) +{ + printf("\t--%s\n", SANITIZE_IPBP_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to instruct the drive to invert the requested\n"); + printf("\t\tsanitize overwrite pattern between each overwrite pass.\n"); + printf("\t\tFor the default pattern of all zeroes, this means that after\n"); + printf("\t\ta first pass of zeroes, the second pass will be all 1's (binary)\n"); + printf("\t\tor all F's (hexadecimal)\n\n"); + } +} + +void print_Sanitize_AUSE_Help(bool shortHelp) +{ + printf("\t--%s\n", SANITIZE_AUSE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to allow running a sanitize operation in\n"); + printf("\t\tunrestricted mode. Without this option, all sanitize options\n"); + printf("\t\tare run in restricted mode by default.\n"); + printf("\t\tIn unrestricted mode, if a sanitize erase fails the drive enters\n"); + printf("\t\ta failure state. The failure state can be cleared with a Sanitize\n"); + printf("\t\texit failure mode command, or it can be cleared with a successful\n"); + printf("\t\tsanitize erase.\n"); + printf("\t\tIn restricted mode, if a sanitize fails, the failure state can only\n"); + printf("\t\tbe cleared with a successful sanitize erase.\n\n"); + } +} + +void print_Zone_No_Reset_Help(bool shortHelp) +{ + printf("\t--%s\n", ZONE_NO_RESET_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tFor ZBD's (Zoned Block Devices), use this option during a\n"); + printf("\t\tSanitize or ATA Security Erase to specify leaving all zones\n"); + printf("\t\tfull so that full verification of erasure can be performed.\n"); + printf("\t\tWhen this option is not specified, all zones will be empty\n"); + printf("\t\tupon completion of these erases.\n\n"); + } +} + +void print_Sanitize_No_Deallocate_Help(bool shortHelp) +{ + printf("\t--%s\t(NVMe Only)\n", NO_DEALLOCATE_AFTER_ERASE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tFor NVMe devices, specify this option during a sanitize to\n"); + printf("\t\tleave all blocks allocated after a sanitize erase. By default\n"); + printf("\t\tan NVMe controller will deallocate (TRIM/Unmap) all the LBAs.\n"); + printf("\t\tUsing this option allows for full verification of erasure after\n"); + printf("\t\ta Sanitize command.\n"); + printf("\t\tNOTE: An NVMe controller may inhibit this option in certain\n"); + printf("\t\tconfigurations meaning the sanitize may produce a warning or\n"); + printf("\t\ta failure depending on how this is configured on the controller.\n"); + printf("\t\tAfter verifying an erasure with this option, run a deallocate/TRIM\n"); + printf("\t\tacross the entire device/namespace to match default behavior of\n"); + printf("\t\ta sanitize erase.\n\n"); + } +} + +void print_Refresh_Filesystems_Help(bool shortHelp) +{ + printf("\t--%s\n", REFRESH_FILE_SYSTEMS_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tThis option will call an OS unique low-level routine to rescan\n"); + printf("\t\ta device for any file systems it can detect through the\n"); + printf("\t\tpartition table. The detected filesystems will vary by OS\n"); + printf("\t\tand OS capabilities.\n"); + printf("\t\tThis option is useful to call after completing a full disk erase\n"); + printf("\t\tas it may make a cached volume in the OS go away or detect that a device\n"); + printf("\t\tis empty and ready to have a new file system written to it.\n\n"); + } +} + void print_Poll_Help(bool shortHelp) { printf("\t--%s\n", POLL_LONG_OPT_STRING); @@ -662,7 +825,7 @@ void print_RevertSP_Help(bool shortHelp) } } -void print_Progress_Help(bool shortHelp, char* testsTogetProgressFor) +void print_Progress_Help(bool shortHelp, const char* testsTogetProgressFor) { printf("\t--%s [%s]\n", PROGRESS_LONG_OPT_STRING, testsTogetProgressFor); if (!shortHelp) @@ -685,6 +848,23 @@ void print_SMART_Check_Help(bool shortHelp) } } +void print_SMART_Offline_Data_Collection_Help(bool shortHelp) +{ + printf("\t--%s\t(SATA Only)\n", SHORT_DST_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tExecute the SMART off-line data collection routine on an ATA drive.\n"); + printf("\t\tThis will run for the amount of time the device specifies that this\n"); + printf("\t\toperation will take to complete. Progress updates are not available\n"); + printf("\t\twhile this is running. Some drives allow other commands to be processed\n"); + printf("\t\tand some require no interruption while this routine completes.\n"); + printf("\t\tThis routine does vendor unique activities to update the SMART data and\n"); + printf("\t\tSMART attributes the device reports.\n"); + printf("\t\tIf the SMART auto-off-line feature is supported and enabled, then this\n"); + printf("\t\troutine is already running automatically in the background periodically.\n\n"); + } +} + void print_Short_DST_Help(bool shortHelp) { printf("\t--%s\n", SHORT_DST_LONG_OPT_STRING); @@ -1044,7 +1224,7 @@ void print_extSmatLog_Help(bool shortHelp) } } -void print_pcierr_Help (bool shortHelp) +void print_pcierr_Help(bool shortHelp) { printf("\t--%s\n", CLEAR_PCIE_CORRECTABLE_ERRORS_LONG_OPT_STRING); if (!shortHelp) @@ -1077,6 +1257,16 @@ void print_Show_NVM_Power_States_Help(bool shortHelp) } } +void print_Show_Phy_Event_Counters_Help(bool shortHelp) +{ + printf("\t--%s\t(SATA Only)\n", SHOW_PHY_EVENT_COUNTERS_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to display a SATA device's supported\n"); + printf("\t\tevent counters.\n\n"); + } +} + void print_Transition_Power_Help(bool shortHelp) { printf("\t--%s [active | idle | idleUnload | standby | idle_a | idle_b | idle_c | standby_y | standby_z | sleep]\n", TRANSITION_POWER_MODE_LONG_OPT_STRING); @@ -1401,11 +1591,11 @@ void print_Test_Unit_Ready_Help(bool shortHelp) void print_Fast_Discovery_Help(bool shortHelp) { - printf("\t--%s\n", FAST_DISCOVERY_LONG_OPT_STRING); - if (!shortHelp) - { - printf("\t\tUse this option to issue a fast scan on the specified drive. \n\n"); - } + printf("\t--%s\n", FAST_DISCOVERY_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to issue a fast scan on the specified drive. \n\n"); + } } void print_Firmware_Download_Help(bool shortHelp) @@ -2246,9 +2436,9 @@ void print_Format_Unit_Help(bool shortHelp) printf("\t\tsupported/required sector sizes!\n\n"); printf("\t\tWARNING: Format Unit may affect all LUNs/namespaces for devices\n"); printf("\t\t with multiple logical units or namespaces.\n\n"); - printf("\t\tWARNING: Customer unique firmware may have specific requirements that \n"); - printf("\t\t restrict sector sizes on some products. It may not be possible to format/ \n"); - printf("\t\t fast format to common sizes like 4K or 512B due to these customer requirements.\n\n"); + printf("\t\tWARNING: Customer unique firmware may have specific requirements that \n"); + printf("\t\t restrict sector sizes on some products. It may not be possible to format/ \n"); + printf("\t\t fast format to common sizes like 4K or 512B due to these customer requirements.\n\n"); } } @@ -2508,9 +2698,9 @@ void print_Show_Supported_Formats_Help(bool shortHelp) printf("\t\tand later) On SATA, this is the sector configuration log. (ACS4\n"); printf("\t\tand later) If the device does not report supported sector\n"); printf("\t\tsizes, please consult your product manual.\n\n"); - printf("\t\tWARNING: Customer unique firmware may have specific requirements that \n"); - printf("\t\t restrict sector sizes on some products. It may not be possible to format/ \n"); - printf("\t\t fast format to common sizes like 4K or 512B due to these customer requirements.\n\n"); + printf("\t\tWARNING: Customer unique firmware may have specific requirements that \n"); + printf("\t\t restrict sector sizes on some products. It may not be possible to format/ \n"); + printf("\t\t fast format to common sizes like 4K or 512B due to these customer requirements.\n\n"); } } @@ -2653,6 +2843,33 @@ void print_Set_APM_Level_Help(bool shortHelp) } } +void print_WRV_Help(bool shortHelp) +{ + printf("\t--%s [ info | all | vendor | # | disable ]\t(SATA Only)\n", WRV_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tThis option can report the current configuration of the\n"); + printf("\t\tATA Write-Read-Verify feature, enable the feature, or\n"); + printf("\t\tdisable the feature.\n"); + printf("\t\tEnabling this feature instructs the device to perform a\n"); + printf("\t\tverification of all data after it has been written.\n"); + printf("\t\tEnabling this may result in lower device performance.\n"); + printf("\t\tIf write caching is enabled, this feature may return\n"); + printf("\t\tcompletion before writing to the medium and verifying\n"); + printf("\t\tthe medium. If Write caching is disabled, the write and\n"); + printf("\t\tverification must complete before returning command status.\n"); + printf("\t\tArgument usage:\n"); + printf("\t\t info - Display the current status of the feature\n"); + printf("\t\t all - set verification on for all written sectors\n"); + printf("\t\t vendor - set verification for the 1st vendor specific\n"); + printf("\t\t number of sectors.\n"); + printf("\t\t # - Perform verification for the first user defined\n"); + printf("\t\t number of sectors. Note: This is rounded up to the\n"); + printf("\t\t nearest 1024 sectors. Max value of 261120 sectors.\n"); + printf("\t\t disable - disable the Write-Read-Verify feature.\n\n"); + } +} + void print_Show_APM_Level_Help(bool shortHelp) { printf("\t--%s (SATA Only)\n", SHOW_APM_LEVEL_LONG_OPT_STRING); @@ -2675,11 +2892,17 @@ void print_Disable_APM_Help(bool shortHelp) void print_PUIS_Feature_Help(bool shortHelp) { - printf("\t--%s [ enable | disable ] (SATA Only)\n", PUIS_FEATURE_LONG_OPT_STRING); + printf("\t--%s [ info | spinup | enable | disable ] (SATA Only)\n", PUIS_FEATURE_LONG_OPT_STRING); if (!shortHelp) { printf("\t\tUse this option to enable or disable the power up in standby\n"); printf("\t\t(PUIS) feature on SATA drives. \n"); + printf("\t\tArguments:\n"); + printf("\t\t info - display information about the PUIS support on the device\n"); + printf("\t\t spinup - issue the PUIS spinup set features command to spin up\n"); + printf("\t\t the device to active/idle state.\n"); + printf("\t\t enable - enable the PUIS feature using setfeatures command\n"); + printf("\t\t disable - disable the PUIS feature using setfeatures command\n"); printf("\t\tNote: If this is configured on the drive with a jumper, this\n"); printf("\t\t command will fail.\n"); printf("\t\tNote2: Not all products support this feature.\n"); @@ -3020,6 +3243,12 @@ void print_Error_In_Cmd_Line_Args(const char * optstring, const char * arg) printf("Use -h option to view command line help\n"); } +void print_Error_In_Cmd_Line_Args_Short_Opt(char opt, const char * arg) +{ + printf("\nError in option -%c. Invalid argument given '%s'.\n", opt, arg); + printf("Use -h option to view command line help\n"); +} + void print_Enable_Legacy_USB_Passthrough_Help(bool shortHelp) { printf("\t--%s\n", ENABLE_LEGACY_PASSTHROUGH_LONG_OPT_STRING); @@ -3049,7 +3278,7 @@ int parse_Device_Handle_Argument(char * optarg, bool *allDrives, bool *userHandl return 254;//one of the required parameters is missing. handleList is checked below... } /*get the number out of optarg to tack onto the device handle*/ - if (NULL != optarg) + if (M_NULLPTR != optarg) { if (strcmp(optarg, "all") == 0) { @@ -3061,70 +3290,70 @@ int parse_Device_Handle_Argument(char * optarg, bool *allDrives, bool *userHandl *userHandleProvided = true; #if defined(_WIN32) #define WINDOWS_MAX_HANDLE_STRING_LENGTH 50 - char windowsHandle[WINDOWS_MAX_HANDLE_STRING_LENGTH] = { 0 }; - char *deviceHandle = &windowsHandle[0]; - char *physicalDeviceNumber; /*making this a string in case the handle is two or more digits long*/ - /*make sure the user gave us "PD" for the device handle...*/ - if (_strnicmp(optarg, "PD", 2) == 0) - { - physicalDeviceNumber = strpbrk(optarg, "0123456789"); - snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "\\\\.\\PhysicalDrive%s", physicalDeviceNumber); - } + DECLARE_ZERO_INIT_ARRAY(char, windowsHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH); + char *deviceHandle = &windowsHandle[0]; + char *physicalDeviceNumber; /*making this a string in case the handle is two or more digits long*/ + /*make sure the user gave us "PD" for the device handle...*/ + if (_strnicmp(optarg, "PD", 2) == 0) + { + physicalDeviceNumber = strpbrk(optarg, "0123456789"); + snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "\\\\.\\PhysicalDrive%s", physicalDeviceNumber); + } #if defined(ENABLE_CSMI) - else if (strncmp(optarg, "csmi", 4) == 0) - { - snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); - } + else if (strncmp(optarg, "csmi", 4) == 0) + { + snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); + } #endif - else if (strncmp(optarg, "\\\\.\\", 4) == 0) - { - snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); - } - /*If we want to add another format for accepting a handle, then add an else-if here*/ - else /*we have an invalid handle*/ - { - printf("Error: %s is an invalid handle format for this tool.\n", optarg); - exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); - } + else if (strncmp(optarg, "\\\\.\\", 4) == 0) + { + snprintf(deviceHandle, WINDOWS_MAX_HANDLE_STRING_LENGTH, "%s", optarg); + } + /*If we want to add another format for accepting a handle, then add an else-if here*/ + else /*we have an invalid handle*/ + { + printf("Error: %s is an invalid handle format for this tool.\n", optarg); + exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); + } #else - char *deviceHandle = optarg; + char *deviceHandle = optarg; #endif - ++(*deviceCount);/*increment this variable if we've made it this far.*/ - /*The code below is where this function gets complicated. Be very careful changing anything below this comment.*/ - if (!*handleList) - { - /*allocate the list and add this handle to it.*/ - *handleList = C_CAST(char**, calloc((*deviceCount), sizeof(char*))); - if (!*handleList) - { - perror("error allocating memory for handle list\n"); - return 255; - } - } - else - { - /*list already allocated, so reallocate and add this next handle to it.*/ - char **temp = C_CAST(char**, realloc(*handleList, (*deviceCount) * sizeof(char*))); - if (!temp) - { - perror("error reallocating memory for handle list\n"); - return 255; - } - *handleList = temp; - } - /*the list has been allocated, now put the handle we've received into the list*/ - /*start by allocating memory for the handle at the new list location*/ - size_t handleListNewHandleLength = strlen(deviceHandle) + 1; - (*handleList)[(*deviceCount) - 1] = C_CAST(char*, calloc(handleListNewHandleLength, sizeof(char))); - if (!(*handleList)[(*deviceCount) - 1]) - { - perror("error allocating memory for adding device handle to list\n"); - return 255; - } - /*copy the handle into memory*/ - snprintf((*handleList)[(*deviceCount) - 1], handleListNewHandleLength, "%s", deviceHandle); - } + ++(*deviceCount);/*increment this variable if we've made it this far.*/ + /*The code below is where this function gets complicated. Be very careful changing anything below this comment.*/ + if (!*handleList) + { + /*allocate the list and add this handle to it.*/ + *handleList = C_CAST(char**, safe_calloc((*deviceCount), sizeof(char*))); + if (!*handleList) + { + perror("error allocating memory for handle list\n"); + return 255; + } + } + else + { + /*list already allocated, so reallocate and add this next handle to it.*/ + char **temp = C_CAST(char**, safe_reallocf(C_CAST(void**, handleList), (*deviceCount) * sizeof(char*))); + if (!temp) + { + perror("error reallocating memory for handle list\n"); + return 255; + } + *handleList = temp; + } + /*the list has been allocated, now put the handle we've received into the list*/ + /*start by allocating memory for the handle at the new list location*/ + size_t handleListNewHandleLength = safe_strlen(deviceHandle) + 1; + (*handleList)[(*deviceCount) - 1] = C_CAST(char*, safe_calloc(handleListNewHandleLength, sizeof(char))); + if (!(*handleList)[(*deviceCount) - 1]) + { + perror("error allocating memory for adding device handle to list\n"); + return 255; + } + /*copy the handle into memory*/ + snprintf((*handleList)[(*deviceCount) - 1], handleListNewHandleLength, "%s", deviceHandle); + } } return 0; } @@ -3135,9 +3364,9 @@ void free_Handle_List(char ***handleList, uint32_t listCount) { for (uint32_t handleIter = 0; handleIter < listCount; ++handleIter) { - safe_Free((*handleList)[handleIter]) + safe_free(&(*handleList)[handleIter]); } - safe_Free((*handleList)) + safe_free((*handleList)); } } @@ -4102,12 +4331,12 @@ void print_No_Time_Limit_Help(bool shortHelp) void print_No_Banner_Help(bool shortHelp) { - printf("\t--%s\n", NO_BANNER_OPT_STRING); - if (!shortHelp) - { - printf("\t\tUse this option to suppress the text banner that displays each time\n"); - printf("\t\topenSeaChest is run.\n\n"); - } + printf("\t--%s\n", NO_BANNER_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to suppress the text banner that displays each time\n"); + printf("\t\topenSeaChest is run.\n\n"); + } } void print_Show_Power_Telemetry_Help(bool shortHelp) @@ -4550,3 +4779,657 @@ void print_DCO_Disable_Features_Help(bool shortHelp) } } +void print_Raw_CDB_Length_Help(bool shortHelp) +{ + printf("\t--%s [length in bytes]\n", RAW_CDB_LEN_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the length of the CDB\n"); + printf("\t\tto send to the device. Max length is %" PRIu8 "\n", UINT8_MAX); + printf("\t\tSome OS's may not support CDBs larger than 16 bytes\n\n"); + } +} + +void print_Raw_CDB_Help(bool shortHelp) +{ + printf("\t--%s [csv CDB]\n", RAW_CDB_ARRAY_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify a specific CDB to\n"); + printf("\t\tsend to a device. The entered value must be\n"); + printf("\t\tin comma separated value (csv) format. To\n"); + printf("\t\tspecify a value as hex, it must be either\n"); + printf("\t\tpre-pended with \"0x\" or post-pended with\n"); + printf("\t\t\"h\" or \"H\"\n"); + printf("\t\tExamples:\n"); + printf("\t\t\t1) inquiry: --%s 12h,0,0,0,60h,0\n", RAW_CDB_ARRAY_LONG_OPT_STRING); + printf("\t\t\t2) inquiry: --%s 0x12,0,0,0,0x60,0\n", RAW_CDB_ARRAY_LONG_OPT_STRING); + printf("\t\t\t3) inquiry: --%s 18,0,0,0,96,0\n", RAW_CDB_ARRAY_LONG_OPT_STRING); + printf("\t\tAll 3 examples send the same command to a drive\n\n"); + } +} + +void print_Raw_TFR_Command_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_COMMAND_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the command operation code for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_Feature_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_FEATURE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the feature register for\n"); + printf("\t\tsending a raw SATA command. (Lower 8 bits on 48 bit commands)\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_Feature_Ext_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_FEATURE_EXT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the feature ext register for\n"); + printf("\t\tsending a raw SATA command. (Upper 8 bits on 48 bit commands)\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_Feature_Full_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_FEATURE_FULL_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the feature and feature ext register for\n"); + printf("\t\tsending a raw SATA command. This will be interpretted as a 16bit value.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_Low_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_LOW_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA low (sector number) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_Mid_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_MID_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA mid (Cylinder Low) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_High_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_HIGH_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA high (Cylinder High) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_Low_Ext_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_LOW_EXT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA low ext (sector number ext) register for\n"); + printf("\t\tsending a raw SATA command. This is for 48 bit commands.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_Mid_Ext_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_MID_EXT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA mid ext (Cylinder Low ext) register for\n"); + printf("\t\tsending a raw SATA command. This is for 48 bit commands.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_High_Ext_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_HIGH_EXT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA high ext (Cylinder High) ext register for\n"); + printf("\t\tsending a raw SATA command. This is for 48 bit commands.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_Full_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_LBA_FULL_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the LBA registers for\n"); + printf("\t\tsending a raw SATA command. This will be interpretted as a 48 bit value\n"); + printf("\t\tto put into the appropriate LBA registers. This option is more useful when specifying\n"); + printf("\t\tan LBA value for a command like a read or a write.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_Device_Head_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_DEVICE_HEAD_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the Device/Head register for\n"); + printf("\t\tsending a raw SATA command. If this option is not provided, a value of\n"); + printf("\t\tA0h will be used for backwards compatibility with older ATA command specifications.\n"); + printf("\t\tNOTE: This option should be specified BEFORE the --%s option\n", RAW_TFR_LBA_MODE_BIT_LONG_OPT_STRING); + printf("\t\tNOTE: On 28bit read/write commands, the high 4 bits of the LBA register need to be\n"); + printf("\t\t placed in the lower 4 bits of this register.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_LBA_Mode_Help(bool shortHelp) +{ + printf("\t--%s\t(SATA Only)\n", RAW_TFR_LBA_MODE_BIT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to set the LBA Mode bit of the Device/Head register for\n"); + printf("\t\tsending a raw SATA command. \n"); + printf("\t\tThis bit is necessary for performing read/write commands on modern drives.\n"); + printf("\t\tNOTE: This bit will NOT be set by default since it only applies to read/write commands\n"); + printf("\t\t but not all other commands in the ATA specifications.\n"); + printf("\n"); + } +} + +void print_Raw_TFR_Sector_Count_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_SECTOR_COUNT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the sector count register for\n"); + printf("\t\tsending a raw SATA command. (Lower 8 bits on 48 bit commands)\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_Sector_Count_Ext_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the sector count ext register for\n"); + printf("\t\tsending a raw SATA command. (Upper 8 bits on 48 bit commands)\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_Sector_Count_Full_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the sector count and sector count ext register for\n"); + printf("\t\tsending a raw SATA command. This will be interpretted as a 16bit value.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n\n"); + } +} + +void print_Raw_TFR_ICC_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_ICC_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the ICC register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n"); + printf("\t\tNOTE: Not all interfaces support setting this register. 32B SAT CDB required.\n\n"); + } +} + +void print_Raw_TFR_AUX1_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_AUX1_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the Aux (7:0) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n"); + printf("\t\tNOTE: Not all interfaces support setting this register. 32B SAT CDB required.\n\n"); + } +} + +void print_Raw_TFR_AUX2_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_AUX2_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the Aux (15:8) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n"); + printf("\t\tNOTE: Not all interfaces support setting this register. 32B SAT CDB required.\n\n"); + } +} + +void print_Raw_TFR_AUX3_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_AUX3_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the Aux (23:16) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n"); + printf("\t\tNOTE: Not all interfaces support setting this register. 32B SAT CDB required.\n\n"); + } +} + +void print_Raw_TFR_AUX4_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_AUX4_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the Aux (31:24) register for\n"); + printf("\t\tsending a raw SATA command.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n"); + printf("\t\tNOTE: Not all interfaces support setting this register. 32B SAT CDB required.\n\n"); + } +} + +void print_Raw_TFR_Aux_Full_Help(bool shortHelp) +{ + printf("\t--%s [hex or decimal]\t(SATA Only)\n", RAW_TFR_AUX_FULL_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the Aux (31:0) registers for\n"); + printf("\t\tsending a raw SATA command. This will be interpretted as a 32bit value.\n"); + printf("\t\tThe value should be specified in hex as ??h or 0x?? or as a decimale value\n"); + printf("\t\tNOTE: Not all interfaces support setting these registers. 32B SAT CDB required.\n\n"); + } +} + +void print_Raw_TFR_Protocol_Help(bool shortHelp) +{ + printf("\t--%s [pio | dma | udma | fpdma | ncq | nodata | reset | dmaque | diag]\t(SATA Only)\n", RAW_TFR_PROTOCOL_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the protocol for\n"); + printf("\t\tsending a raw SATA command. This option must match the definition\n"); + printf("\t\tof the command in the ATA/ACS specification.\n"); + printf("\t\tThis option must be provided before a command will be sent.\n"); + printf("\t\tArguments:\n"); + printf("\t\t pio - send as programmed IO protocol.\n"); + printf("\t\t dma - send as direct memory access protocol\n"); + printf("\t\t udma - send as ultra direct memory access protocol\n"); + printf("\t\t fpdma/ncq - send as first party direct memory access protocol (NCQ)\n"); + printf("\t\t nodata - send as non-data protocol\n"); + printf("\t\t reset - send as reset protocol (ATAPI only)\n"); + printf("\t\t dmaque - send as direct memory access queued protocol (TCQ)\n"); + printf("\t\t diag - send as devie diagnostic protocol\n"); + printf("\t\tNOTE: If a command with dma doesn't work, try udma. Some SATLs like it better.\n"); + printf("\t\tNOTE: Most SATLs don't allow sending queued commands as pass-through. Some OSs\n"); + printf("\t\t also will not allow queued pass-through commands.\n\n"); + } +} + +void print_Raw_TFR_XFer_Length_Register_Help(bool shortHelp) +{ + printf("\t--%s [sectorCount | feature | tpsiu | nodata]\t(SATA Only)\n", RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the registers used to specify the length of data\n"); + printf("\t\tbeing sent or received when issuing a raw SATA command. This option must match\n"); + printf("\t\tthe definition of the command in the ATA/ACS specification.\n"); + printf("\t\tThis option must be provided before a command will be sent.\n"); + printf("\t\tArguments:\n"); + printf("\t\t sectorCount - the sector count registers specify the number of blocks (most commands)\n"); + printf("\t\t feature - the feature registers specify the number of blocks (queued commands)\n"); + printf("\t\t tpsiu - a transport specific location will specify the length of the data transfer\n"); + printf("\t\t nodata - no data transfer. Used on non-data protocol commands\n"); + printf("\t\tNOTE: tpsiu is generally only seen supported on USB adapters, but not all USB SATL's\n"); + printf("\t\t will recognize this option.\n"); + printf("\t\tNOTE: For commands, such as identify (ECh), that transfer data, but do not specify\n"); + printf("\t\t a value of 1 in the sector count, it is recommended that this is added\n"); + printf("\t\t to the sector count register and and \"sectorCount\" is used for better\n"); + printf("\t\t compatibility with various SATLs.\n\n"); + } +} + +void print_Raw_TFR_Byte_Block_Help(bool shortHelp) +{ + printf("\t--%s [512 | logical | bytes | nodata]\t(SATA Only)\n", RAW_TFR_BYTE_BLOCK_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the data transfer length\n"); + printf("\t\tbeing sent or received when issuing a raw SATA command. This option must match\n"); + printf("\t\tthe definition of the command in the ATA/ACS specification.\n"); + printf("\t\tThis option must be provided before a command will be sent.\n"); + printf("\t\tArguments:\n"); + printf("\t\t 512 - the data transfer is a number of 512B blocks (most commands)\n"); + printf("\t\t logical - data transfer is a number of logical block sizes transfers (read commands)\n"); + printf("\t\t bytes - the data transfer is a specific number of bytes (some legacy commands or tpsiu is used)\n"); + printf("\t\t nodata - no data transfer. Used on non-data protocol commands\n"); + printf("\t\tNOTE: All read/write commands should use \"logical\", all other data transfers should use 512\n\n"); + } +} + +void print_Raw_TFR_Size_Help(bool shortHelp) +{ + printf("\t--%s [28 | 48 | complete]\t(SATA Only)\n", RAW_TFR_SIZE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the command type: 28bit or 48bit\n"); + printf("\t\twhen issuing a raw SATA command. This option must match\n"); + printf("\t\tthe definition of the command in the ATA/ACS specification.\n"); + printf("\t\tThis option must be provided before a command will be sent.\n"); + printf("\t\tArguments:\n"); + printf("\t\t 28 - the command is a 28 bit command (ex: identify, SMART)\n"); + printf("\t\t 48 - the command is a 48 bit command (ex: read DMA ext, read log ext)\n"); + printf("\t\t complete - 48 bit command that also sets ICC or AUX registers.\n"); + printf("\t\t use this to force a 32B CDB. If specifying 48 and AUX or ICC\n"); + printf("\t\t are set, 32B CDB will automatically be generated without needing\n"); + printf("\t\t this option explicitly set.\n"); + printf("\t\tNOTE: complete TFR requires SAT 32B cdb, which many devices or interfaces\n"); + printf("\t\t may not support. These commands may not be available.\n\n"); + } +} + +void print_Raw_TFR_Check_Condition_Help(bool shortHelp) +{ + printf("\t--%s\t(SATA Only)\n", RAW_TFR_CHECK_CONDITION_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to set the check condition bit in the SAT CDB that may be\n"); + printf("\t\tsent to a translator to inform it to generate a check condition and return\n"); + printf("\t\tall task file results.\n"); + printf("\t\tNOTE: This option may not work on all SATLs.\n\n"); + } +} + +void print_Raw_Data_Length_Help(bool shortHelp) +{ + printf("\t--%s [length in bytes]\n", RAW_DATA_LEN_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the data transfer\n"); + printf("\t\tlength for a data-in or data-out transfer.\n"); + printf("\t\tThe following post fixes are allowed for\n"); + printf("\t\tspecifying a transfer length:\n"); + printf("\t\t\tBLOCKS - used to specify a transfer length\n"); + printf("\t\t\t\tin device logical blocks. (Preferred)\n"); + printf("\t\t\tKB - length in kilobytes (val * 1000)\n"); + printf("\t\t\tKiB - length in kibibytes (val * 1024)\n"); + printf("\t\t\tMB - length in megabytes (val * 1000000)\n"); + printf("\t\t\tMiB - length in mebibytes (val * 1048576)\n"); + printf("\t\tYou must enter a size that is greater than or\n"); + printf("\t\tequal to any length in the entered raw command\n"); + printf("\t\tdata. If a lesser value is entered, then the\n"); + printf("\t\tutility may experience errors or crash.\n\n"); + } +} + +void print_Raw_Data_Direction_Help(bool shortHelp) +{ + printf("\t--%s [in | out | none]\n", RAW_DATA_DIRECTION_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the data direction\n"); + printf("\t\tof the entered raw command.\n"); + printf("\t\tin - transfer data from the device to host\n"); + printf("\t\tout - transfer data from the host to device\n"); + printf("\t\tnone - no data is transferred\n"); + } +} + +void print_Raw_Output_File_Help(bool shortHelp) +{ + printf("\t--%s [path/filename]\n", RAW_OUTPUT_FILE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify an output file to\n"); + printf("\t\tsave data returned from a command, or in the\n"); + printf("\t\tcase of an error, the returned error buffer.\n"); + printf("\t\tThis option will always append data to already\n"); + printf("\t\tcreated files. If an error occurs on a datain\n"); + printf("\t\traw command, the returned error data will not be\n"); + printf("\t\tsaved to a file to prevent adding unexpected data\n"); + printf("\t\tto the created file.\n\n"); + } +} + +void print_Raw_Input_File_Help(bool shortHelp) +{ + printf("\t--%s [path/filename]\n", RAW_INPUT_FILE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify an input file to\n"); + printf("\t\tsend to a device. Must be a binary file.\n\n"); + } +} + +void print_Raw_Timeout_Help(bool shortHelp) +{ + printf("\t--%s [time in seconds]\n", RAW_TIMEOUT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify an timeout in seconds\n"); + printf("\t\tfor a raw command being sent to a device.\n\n"); + } +} + +void print_Raw_Input_File_Offset_Help(bool shortHelp) +{ + printf("\t--%s [offset in bytes]\n", RAW_INPUT_FILE_OFFSET_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the offset within\n"); + printf("\t\tthe raw input file to start sending data from.\n"); + printf("\t\tThe following post fixes are allowed for\n"); + printf("\t\tspecifying a transfer length:\n"); + printf("\t\t\tBLOCKS - used to specify an offset length\n"); + printf("\t\t\t\tin device logical blocks. (Preferred)\n"); + printf("\t\t\tKB - length in kilobytes (val * 1000)\n"); + printf("\t\t\tKiB - length in kibibytes (val * 1024)\n"); + printf("\t\t\tMB - length in megabytes (val * 1000000)\n"); + printf("\t\t\tMiB - length in mebibytes (val * 1048576)\n"); + printf("\n"); + } +} + +void print_Check_Pending_List_Help(bool shortHelp) +{ + printf("\t--%s [count to check]\n", CHECK_PENDING_LIST_COUNT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to check if the pending defect list count is\n"); + printf("\t\tgreater than the provided value.\n"); + printf("\t\tNOTE: This only works on SAS products that support the Pending\n"); + printf("\t\tDefects log page from SBC4 or later\n\n"); + } +} + +void print_Check_Grown_List_Help(bool shortHelp) +{ + printf("\t--%s [count to check]\n", CHECK_GROWN_LIST_COUNT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to check if the grown defect list count is\n"); + printf("\t\tgreater than the provided value.\n\n"); + } +} + +void print_Show_Pending_List_Help(bool shortHelp) +{ + printf("\t--%s (Seagate Only)\n", SHOW_PENDING_LIST_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to show the pending defect list\n"); + printf("\t\tas it is reported by the drive.\n"); + printf("\t\tNOTE: SBC4 pending log required for SAS support.\n\n"); + } +} + +void print_Create_Uncorrectable_Help(bool shortHelp) +{ + printf("\t--%s [lba]\t(Seagate Only)\n", CREATE_UNCORRECTABLE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to create a uncorrectable error at\n"); + printf("\t\tthe specified LBA. Use --%s to specify a range.\n", UNCORRECTABLE_RANGE_LONG_OPT_STRING); + printf("\t\tBy default, pseudo uncorrectable errors will be created for\n"); + printf("\t\tthe entire physical sector. Use the --%s option\n", FLAG_UNCORRECTABLE_LONG_OPT_STRING); + printf("\t\tto flag errors instead. Flagged errors do not get logged\n"); + printf("\t\tor have any error processing when encountered.\n\n"); + } +} + +void print_Flag_Uncorrectable_Help(bool shortHelp) +{ + printf("\t--%s\t(Seagate Only)\n", FLAG_UNCORRECTABLE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to flag an uncorrectable error instead of\n"); + printf("\t\tcreating a pseudo uncorrectable error with the\n"); + printf("\t\t--%s or --%s options.\n", CREATE_UNCORRECTABLE_LONG_OPT_STRING, RANDOM_UNCORRECTABLES_LONG_OPT_STRING); + printf("\t\tError types:\n"); + printf("\t\t Pseudo - creates a pseudo uncorrectable error. The device\n"); + printf("\t\t will perform full error recovery and logging on failure.\n"); + printf("\t\t Flagged - flags an error. The device will not perform error\n"); + printf("\t\t recovery and will not log on failure.\n"); + printf("\n"); + } +} + +void print_Uncorrectable_Range_Help(bool shortHelp) +{ + printf("\t--%s [range]\t(Seagate Only)\n", UNCORRECTABLE_RANGE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify a range of LBAs to create an\n"); + printf("\t\tuncorrectable error at. This option must be used with the\n"); + printf("\t\t--%s or --%s options so that a\n", CREATE_UNCORRECTABLE_LONG_OPT_STRING, FLAG_UNCORRECTABLE_LONG_OPT_STRING); + printf("\t\tstarting LBA is specified. \n\n"); + } +} + +void print_Random_Uncorrectable_Help(bool shortHelp) +{ + printf("\t--%s [number of errors]\t(Seagate Only)\n", RANDOM_UNCORRECTABLES_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to create a number of random uncorrectable\n"); + printf("\t\tLBAs on a drive. \n\n"); + } +} + +void print_Disable_Read_Uncorrectables_Help(bool shortHelp) +{ + printf("\t--%s\n", DISABLE_READ_UNCORRECTABLES_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to disable issuing read commands to the LBAs\n"); + printf("\t\twhere errors are written. This option should only be used for\n"); + printf("\t\tdebugging. When this option is used, the uncorrectable errors\n"); + printf("\t\tmay not end up being logged in the Pending Defect List on the\n"); + printf("\t\tdrive.\n\n"); + } +} + +void print_Corrupt_LBA_Help(bool shortHelp) +{ + printf("\t--%s [lba]\t(Seagate Only)\n", CORRUPT_LBA_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to corrupt the data bytes of an LBA. The\n"); + printf("\t\t--%s option can be used to specify the number of bytes to\n", BYTES_TO_CORRUPT_LONG_OPT_STRING); + printf("\t\tcorrupt. If that option is not given, a default will be used\n"); + printf("\t\tthat attempts to create a correctable error on the drive.\n"); + printf("\t\tThis option can be used to create uncorrectable or correctable\n"); + printf("\t\terrors on a drive, depending on it's ECC algorithm and the number\n"); + printf("\t\tof corrupted data bytes.\n\n"); + } +} + +void print_Corrupt_Random_LBAs_Help(bool shortHelp) +{ + printf("\t--%s [# of LBAs to corrupt]\t(Seagate Only)\n", CORRUPT_RANDOM_LBAS_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tThis option will corrupt the specified number of LBAs randomly\n"); + printf("\t\ton the device. The --%s option can be used to specify the number of bytes to\n", BYTES_TO_CORRUPT_LONG_OPT_STRING); + printf("\t\tcorrupt. If that option is not given, a default will be used\n"); + printf("\t\tthat attempts to create a correctable error on the drive.\n"); + printf("\t\tThis option can be used to create uncorrectable or correctable\n"); + printf("\t\terrors on a drive, depending on it's ECC algorithm and the number\n"); + printf("\t\tof corrupted data bytes.\n\n"); + } +} + +void print_Corrupt_Range_Help(bool shortHelp) +{ + printf("\t--%s [# of LBAs]\t(Seagate Only)\n", CORRUPT_LBA_RANGE_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tThis option is used with the --%s option to\n", CORRUPT_LBA_LONG_OPT_STRING); + printf("\t\tcorrupt a range of LBAs on the drive.\n\n"); + } +} + +void print_Bytes_To_Corrupt_Help(bool shortHelp) +{ + printf("\t--%s [# of bytes]\t(Seagate Only)\n", BYTES_TO_CORRUPT_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to specify the number of data bytes to change\n"); + printf("\t\twhen used with the --%s option.\n\n", CORRUPT_LBA_LONG_OPT_STRING); + } +} + +void print_SCSI_FW_Info_Help(bool shortHelp) +{ + printf("\t--%s (SAS Only)\n", SHOW_SCSI_FW_INFO_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tThis option will show the SCSI Firmware info from\n"); + printf("\t\ta Seagate SAS drive. This is the extended firmware build\n"); + printf("\t\tinformation.\n\n"); + } +} + +void print_Capacity_Model_Number_Mapping_Help(bool shortHelp) +{ + printf("\t--%s\n", CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to display the capacity model number mapping\n"); + printf("\t\tTBD\n\n"); + } +} + +void print_Change_Id_String_Help(bool shortHelp) +{ + printf("\t--%s\n", CHANGE_ID_STRING_LONG_OPT_STRING); + if (!shortHelp) + { + printf("\t\tUse this option to change ID string according to capacity - model number\n"); + printf("\t\tmapping. Need to use together with --%s or --%s\n\n", SET_MAX_LBA_LONG_OPT_STRING, RESTORE_MAX_LBA_LONG_OPT_STRING); + } +} diff --git a/subprojects/opensea-common b/subprojects/opensea-common index bb04dc02..760fb5b5 160000 --- a/subprojects/opensea-common +++ b/subprojects/opensea-common @@ -1 +1 @@ -Subproject commit bb04dc02a0276afbee9f7b3b1d51cd3d15522241 +Subproject commit 760fb5b528ffe83b11128f659ecd94aafebeca6d diff --git a/subprojects/opensea-operations b/subprojects/opensea-operations index 8f39ad13..7f619fe5 160000 --- a/subprojects/opensea-operations +++ b/subprojects/opensea-operations @@ -1 +1 @@ -Subproject commit 8f39ad13b2cc02af6afeccb163540608590db91c +Subproject commit 7f619fe57e88d11c3f386c845881c4f86cf2b1f7 diff --git a/subprojects/opensea-transport b/subprojects/opensea-transport index 0dff1bd2..4188a584 160000 --- a/subprojects/opensea-transport +++ b/subprojects/opensea-transport @@ -1 +1 @@ -Subproject commit 0dff1bd23e895807b7dc4f8578d80f3da539d9f9 +Subproject commit 4188a5849222d7ea6b6cb2f47093312ce6bbb221 diff --git a/subprojects/wingetopt b/subprojects/wingetopt index 7e78cda0..1378f031 160000 --- a/subprojects/wingetopt +++ b/subprojects/wingetopt @@ -1 +1 @@ -Subproject commit 7e78cda08d1a9d739ec111fe56d6c1e1d30a5677 +Subproject commit 1378f031b0a0480dc78bfdbacce798496413b7f6 diff --git a/utils/C/openSeaChest/openSeaChest_Basics.c b/utils/C/openSeaChest/openSeaChest_Basics.c index 887de72c..205be920 100644 --- a/utils/C/openSeaChest/openSeaChest_Basics.c +++ b/utils/C/openSeaChest/openSeaChest_Basics.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -11,17 +12,20 @@ // // // \file OpenSeaChest_Basics.c command line that performs various basic functions on a device. - +//test ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "sleep.h" +#include "secure_file.h" + #include "getopt.h" -#include "common.h" #include "EULA.h" #include "openseachest_util_options.h" #include "drive_info.h" @@ -39,7 +43,7 @@ //////////////////////// const char *util_name = "openSeaChest_Basics"; -const char *buildVersion = "3.5.4"; +const char *buildVersion = "3.6.2"; //////////////////////////// // functions to declare // @@ -66,10 +70,12 @@ int main(int argc, char *argv[]) // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR + CAPACITY_MODEL_NUMBER_MAPPING_VAR + CHANGE_ID_STRING_VAR SAT_INFO_VAR DATA_ERASE_VAR POSSIBLE_DATA_ERASE_VAR @@ -127,7 +133,7 @@ int main(int argc, char *argv[]) SHOW_CONCURRENT_RANGES_VAR LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -136,6 +142,8 @@ int main(int argc, char *argv[]) DEVICE_LONG_OPT, HELP_LONG_OPT, DEVICE_INFO_LONG_OPT, + CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT, + CHANGE_ID_STRING_LONG_OPT, SAT_INFO_LONG_OPT, USB_CHILD_INFO_LONG_OPT, SCAN_LONG_OPT, @@ -231,11 +239,11 @@ int main(int argc, char *argv[]) //parse long options that have no short option and required arguments here if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { - if (strlen(optarg) == strlen(DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, DATA_ERASE_ACCEPT_STRING, strlen(DATA_ERASE_ACCEPT_STRING)) == 0) + if (strcmp(optarg, DATA_ERASE_ACCEPT_STRING) == 0) { DATA_ERASE_FLAG = true; } - else if (strlen(optarg) == strlen(POSSIBLE_DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, POSSIBLE_DATA_ERASE_ACCEPT_STRING, strlen(POSSIBLE_DATA_ERASE_ACCEPT_STRING)) == 0) + else if (strcmp(optarg, POSSIBLE_DATA_ERASE_ACCEPT_STRING) == 0) { POSSIBLE_DATA_ERASE_FLAG = true; } @@ -247,7 +255,7 @@ int main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TRIM_RANGE_LONG_OPT_STRING) == 0 || strcmp(longopts[optionIndex].name, UNMAP_RANGE_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &TRIM_UNMAP_RANGE_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &TRIM_UNMAP_RANGE_FLAG)) { if (strcmp(longopts[optionIndex].name, TRIM_RANGE_LONG_OPT_STRING) == 0) { @@ -262,7 +270,7 @@ int main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TRIM_LONG_OPT_STRING) == 0 || strcmp(longopts[optionIndex].name, UNMAP_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &TRIM_UNMAP_START_FLAG)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &TRIM_UNMAP_START_FLAG)) { RUN_TRIM_UNMAP_FLAG = true; } @@ -294,7 +302,7 @@ int main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, OVERWRITE_RANGE_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &OVERWRITE_RANGE_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &OVERWRITE_RANGE_FLAG)) { print_Error_In_Cmd_Line_Args(OVERWRITE_RANGE_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -302,7 +310,7 @@ int main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, OVERWRITE_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &OVERWRITE_START_FLAG)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &OVERWRITE_START_FLAG)) { RUN_OVERWRITE_FLAG = true; } @@ -327,20 +335,32 @@ int main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, HOURS_TIME_LONG_OPT_STRING) == 0) { - HOURS_TIME_FLAG = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &HOURS_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(HOURS_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, MINUTES_TIME_LONG_OPT_STRING) == 0) { - MINUTES_TIME_FLAG = C_CAST(uint16_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &MINUTES_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(MINUTES_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, SECONDS_TIME_LONG_OPT_STRING) == 0) { - SECONDS_TIME_FLAG = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SECONDS_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(SECONDS_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp(longopts[optionIndex].name, DOWNLOAD_FW_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(DOWNLOAD_FW_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, DOWNLOAD_FW_LONG_OPT_STRING) == 0) { - int scanRet = sscanf(optarg, FIRMWARE_FILE_NAME_MAX_LEN_FORMAT_STR, DOWNLOAD_FW_FILENAME_FLAG); - if (scanRet > 0 && scanRet != EOF) + int res = snprintf(DOWNLOAD_FW_FILENAME_FLAG, FIRMWARE_FILE_NAME_MAX_LEN, "%s", optarg); + if (res > 0 && res <= FIRMWARE_FILE_NAME_MAX_LEN) { DOWNLOAD_FW_FLAG = true; } @@ -350,7 +370,7 @@ int main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, DOWNLOAD_FW_MODE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(DOWNLOAD_FW_MODE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, DOWNLOAD_FW_MODE_LONG_OPT_STRING) == 0) { DOWNLOAD_FW_MODE = FWDL_UPDATE_MODE_AUTOMATIC; if (strcmp(optarg, "immediate") == 0 || strcmp(optarg, "full") == 0) @@ -384,10 +404,9 @@ int main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SET_MAX_LBA_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_MAX_LBA_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_MAX_LBA_LONG_OPT_STRING) == 0) { - int scanRet = sscanf(optarg, "%" SCNu64, &SET_MAX_LBA_VALUE); - if (scanRet > 0 && scanRet != EOF) + if (get_And_Validate_Integer_Input_Uint64(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_MAX_LBA_VALUE)) { SET_MAX_LBA_FLAG = true; } @@ -397,19 +416,31 @@ int main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SET_PHY_SPEED_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_PHY_SPEED_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_PHY_SPEED_LONG_OPT_STRING) == 0) { - SET_PHY_SPEED_FLAG = true; - SET_PHY_SPEED_GEN = C_CAST(uint8_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_PHY_SPEED_GEN) && SET_PHY_SPEED_GEN < SET_PHY_SPEED_MAX_GENERATION) + { + SET_PHY_SPEED_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(SET_PHY_SPEED_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp(longopts[optionIndex].name, SET_PHY_SAS_PHY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_PHY_SAS_PHY_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_PHY_SAS_PHY_LONG_OPT_STRING) == 0) { - SET_PHY_ALL_PHYS = false; - SET_PHY_SAS_PHY_IDENTIFIER = C_CAST(uint8_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_PHY_SAS_PHY_IDENTIFIER)) + { + SET_PHY_ALL_PHYS = false; + } + else + { + print_Error_In_Cmd_Line_Args(SET_PHY_SAS_PHY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if ((strncmp(longopts[optionIndex].name, SET_READY_LED_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_READY_LED_LONG_OPT_STRING))) == 0) || - (strncmp(longopts[optionIndex].name, SET_PIN_11_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_PIN_11_LONG_OPT_STRING))) == 0) - ) + else if (strcmp(longopts[optionIndex].name, SET_READY_LED_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "default") == 0) { @@ -436,7 +467,7 @@ int main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, READ_LOOK_AHEAD_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(READ_LOOK_AHEAD_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, READ_LOOK_AHEAD_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "info") == 0) { @@ -460,7 +491,7 @@ int main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, WRITE_CACHE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(WRITE_CACHE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, WRITE_CACHE_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "info") == 0) { @@ -484,9 +515,9 @@ int main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, PROVISION_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(PROVISION_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, PROVISION_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &SET_MAX_LBA_VALUE)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &SET_MAX_LBA_VALUE)) { SET_MAX_LBA_FLAG = true; //now, based on the new MaxLBA, set the TRIM/UNMAP start flag to get rid of the LBAs that will not be above the new maxLBA (the range will be set later) @@ -498,7 +529,7 @@ int main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SMART_ATTRIBUTES_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_ATTRIBUTES_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SMART_ATTRIBUTES_LONG_OPT_STRING) == 0) { SMART_ATTRIBUTES_FLAG = true; if (strcmp(optarg, "raw") == 0) @@ -515,29 +546,29 @@ int main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); } else if (strcmp(longopts[optionIndex].name, DISPLAY_LBA_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &DISPLAY_LBA_THE_LBA)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &DISPLAY_LBA_THE_LBA)) { DISPLAY_LBA_FLAG = true; } @@ -623,9 +654,10 @@ int main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -651,7 +683,7 @@ int main(int argc, char *argv[]) } exit(UTIL_EXIT_NO_ERROR); case PROGRESS_SHORT_OPT://progress [test] - PROGRESS_CHAR = strdup(optarg); + PROGRESS_CHAR = optarg; break; default: break; @@ -665,7 +697,7 @@ int main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -762,7 +794,7 @@ int main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -818,6 +850,8 @@ int main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -837,6 +871,8 @@ int main(int argc, char *argv[]) //check that we were given at least one test to perform...if not, show the help and exit if (!(DEVICE_INFO_FLAG || TEST_UNIT_READY_FLAG + //check for other tool specific options here + || CAPACITY_MODEL_NUMBER_MAPPING_FLAG || SMART_CHECK_FLAG || SHORT_DST_FLAG || SMART_ATTRIBUTES_FLAG @@ -857,7 +893,7 @@ int main(int argc, char *argv[]) || PROVISION_FLAG || RUN_OVERWRITE_FLAG || RUN_TRIM_UNMAP_FLAG - || (PROGRESS_CHAR != NULL) + || (PROGRESS_CHAR != M_NULLPTR) || DISPLAY_LBA_FLAG || SHOW_CONCURRENT_RANGES || LOWLEVEL_INFO_FLAG @@ -870,7 +906,7 @@ int main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -913,7 +949,7 @@ int main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -961,11 +997,11 @@ int main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -989,7 +1025,7 @@ int main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -1031,7 +1067,7 @@ int main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1056,7 +1092,7 @@ int main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1096,6 +1132,15 @@ int main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1156,6 +1201,35 @@ int main(int argc, char *argv[]) show_Test_Unit_Ready_Status(&deviceList[deviceIter]); } + if (CAPACITY_MODEL_NUMBER_MAPPING_FLAG) + { + if (is_Change_Identify_String_Supported(&deviceList[deviceIter])) + { + ptrcapacityModelNumberMapping capModelMap = get_Capacity_Model_Number_Mapping(&deviceList[deviceIter]); + if (capModelMap) + { + print_Capacity_Model_Number_Mapping(capModelMap); + delete_Capacity_Model_Number_Mapping(capModelMap); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to get Capacity / Model Number Mapping\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Capacity / Model Number Mapping not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } + } + if (SHOW_CONCURRENT_RANGES) { concurrentRanges ranges; @@ -1186,7 +1260,7 @@ int main(int argc, char *argv[]) if (DISPLAY_LBA_FLAG) { - uint8_t *displaySector = C_CAST(uint8_t*, calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t *displaySector = C_CAST(uint8_t*, safe_calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (!displaySector) { perror("Could not allocate memory to read LBA."); @@ -1202,15 +1276,15 @@ int main(int argc, char *argv[]) } if (SUCCESS == read_LBA(&deviceList[deviceIter], DISPLAY_LBA_THE_LBA, false, displaySector, deviceList[deviceIter].drive_info.deviceBlockSize)) { - printf("\nContents of LBA %"PRIu64":\n", DISPLAY_LBA_THE_LBA); + printf("\nContents of LBA %" PRIu64 ":\n", DISPLAY_LBA_THE_LBA); print_Data_Buffer(displaySector, deviceList[deviceIter].drive_info.deviceBlockSize, true); } else { - printf("Error Reading LBA %"PRIu64" for display\n", DISPLAY_LBA_THE_LBA); + printf("Error Reading LBA %" PRIu64 " for display\n", DISPLAY_LBA_THE_LBA); exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(displaySector) + safe_free_aligned(&displaySector); } if (SPIN_DOWN_FLAG) @@ -1274,12 +1348,19 @@ int main(int argc, char *argv[]) { printf("SMART Check\n"); } - ret = run_SMART_Check(&deviceList[deviceIter], NULL); + smartTripInfo tripInfo; + memset(&tripInfo, 0, sizeof(smartTripInfo)); + ret = run_SMART_Check(&deviceList[deviceIter], &tripInfo); if (FAILURE == ret) { if (VERBOSITY_QUIET < toolVerbosity) { printf("SMART has been tripped!\n"); + if (tripInfo.reasonStringLength > 0) + { + printf("\t%s\n", tripInfo.reasonString); + } + print_SMART_Tripped_Message(is_SSD(&deviceList[deviceIter])); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } @@ -1295,6 +1376,10 @@ int main(int argc, char *argv[]) if (VERBOSITY_QUIET < toolVerbosity) { printf("SMART Warning condition detected!\n"); + if (tripInfo.reasonStringLength > 0) + { + printf("\t%s\n", tripInfo.reasonString); + } } } else @@ -1309,7 +1394,7 @@ int main(int argc, char *argv[]) if (SMART_ATTRIBUTES_FLAG) { - switch (print_SMART_Attributes(&deviceList[deviceIter], SMART_ATTRIBUTES_MODE_FLAG)) + switch (print_SMART_Attributes(&deviceList[deviceIter], C_CAST(eSMARTAttrOutMode, SMART_ATTRIBUTES_MODE_FLAG))) { case SUCCESS: //nothing to print here since if it was successful, the attributes will be printed to the screen @@ -1333,7 +1418,7 @@ int main(int argc, char *argv[]) if (ABORT_DST_FLAG) { - int abortResult = UNKNOWN; + eReturnValues abortResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Aborting DST\n"); @@ -1374,7 +1459,7 @@ int main(int argc, char *argv[]) if (SHORT_DST_FLAG) { - int32_t DSTResult = UNKNOWN; + eReturnValues DSTResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Short DST\n"); @@ -1436,38 +1521,23 @@ int main(int argc, char *argv[]) if (DOWNLOAD_FW_FLAG) { - FILE* firmwareFilePtr = NULL; - bool fileOpenedSuccessfully = true;//assume true in case of activate command - if (DOWNLOAD_FW_MODE != DL_FW_ACTIVATE) + secureFileInfo* fwfile = secure_Open_File(DOWNLOAD_FW_FILENAME_FLAG, "rb", M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (fwfile && fwfile->error == SEC_FILE_SUCCESS) { - //open the file and send the download - if ((firmwareFilePtr = fopen(DOWNLOAD_FW_FILENAME_FLAG, "rb")) == NULL) - { - fileOpenedSuccessfully = false; - } - } - if (DOWNLOAD_FW_MODE == DL_FW_ACTIVATE) - { - //this shouldn't fall into this code path anymore... - fileOpenedSuccessfully = false; - } - if (fileOpenedSuccessfully) - { - size_t firmwareFileSize = C_CAST(size_t, get_File_Size(firmwareFilePtr)); - uint8_t* firmwareMem = C_CAST(uint8_t*, calloc_aligned(firmwareFileSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t* firmwareMem = C_CAST(uint8_t*, safe_calloc_aligned(fwfile->fileSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (firmwareMem) { - if (firmwareFileSize == fread(firmwareMem, sizeof(uint8_t), firmwareFileSize, firmwareFilePtr)) + if (SEC_FILE_SUCCESS == secure_Read_File(fwfile, firmwareMem, fwfile->fileSize, sizeof(uint8_t), fwfile->fileSize, M_NULLPTR)) { firmwareUpdateData dlOptions; memset(&dlOptions, 0, sizeof(firmwareUpdateData)); dlOptions.size = sizeof(firmwareUpdateData); dlOptions.version = FIRMWARE_UPDATE_DATA_VERSION; - dlOptions.dlMode = DOWNLOAD_FW_MODE; + dlOptions.dlMode = C_CAST(eFirmwareUpdateMode, DOWNLOAD_FW_MODE); dlOptions.segmentSize = 0; dlOptions.ignoreStatusOfFinalSegment = M_ToBool(FWDL_IGNORE_FINAL_SEGMENT_STATUS_FLAG); dlOptions.firmwareFileMem = firmwareMem; - dlOptions.firmwareMemoryLength = C_CAST(uint32_t, firmwareFileSize);//firmware files shouldn't be larger than a few MBs for a LONG time + dlOptions.firmwareMemoryLength = C_CAST(uint32_t, fwfile->fileSize);//firmware files shouldn't be larger than a few MBs for a LONG time dlOptions.firmwareSlot = 0; ret = firmware_Download(&deviceList[deviceIter], &dlOptions); switch (ret) @@ -1482,7 +1552,7 @@ int main(int argc, char *argv[]) { printf("The Operating system has reported that a power cycle is required to complete the firmware update\n"); } - if (DOWNLOAD_FW_MODE == DL_FW_DEFERRED) + if (DOWNLOAD_FW_MODE == FWDL_UPDATE_MODE_DEFERRED) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1530,11 +1600,19 @@ int main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(firmwareMem) + safe_free_aligned(&firmwareMem); } else { perror("failed to allocate memory"); + if (fwfile) + { + if (SEC_FILE_SUCCESS != secure_Close_File(fwfile)) + { + printf("secure file structure could not be closed! This is a fatal error!\n"); + } + free_Secure_File_Info(&fwfile); + } exit(255); } } @@ -1542,11 +1620,18 @@ int main(int argc, char *argv[]) { if (VERBOSITY_QUIET < toolVerbosity) { - perror("fopen"); printf("Couldn't open file %s\n", DOWNLOAD_FW_FILENAME_FLAG); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + if (fwfile) + { + if (SEC_FILE_SUCCESS != secure_Close_File(fwfile)) + { + printf("secure file structure could not be closed! This is a fatal error!\n"); + } + free_Secure_File_Info(&fwfile); + } } if (ACTIVATE_DEFERRED_FW_FLAG) @@ -1564,7 +1649,7 @@ int main(int argc, char *argv[]) dlOptions.version = FIRMWARE_UPDATE_DATA_VERSION; dlOptions.dlMode = FWDL_UPDATE_MODE_ACTIVATE; dlOptions.segmentSize = 0; - dlOptions.firmwareFileMem = NULL; + dlOptions.firmwareFileMem = M_NULLPTR; dlOptions.firmwareMemoryLength = 0; dlOptions.firmwareSlot = 0; dlOptions.ignoreStatusOfFinalSegment = false;//NOTE: This flag is not needed or used on products that support deferred download today. @@ -1892,7 +1977,7 @@ int main(int argc, char *argv[]) case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully trimmed/unmapped LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Successfully trimmed/unmapped LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } break; case NOT_SUPPORTED: @@ -1905,7 +1990,7 @@ int main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to trim/unmap LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Failed to trim/unmap LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -1937,11 +2022,11 @@ int main(int argc, char *argv[]) if (DATA_ERASE_FLAG) { //check the time - uint64_t overwriteSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * 60) + (HOURS_TIME_FLAG * 3600); + uint64_t overwriteSeconds = C_CAST(uint64_t, SECONDS_TIME_FLAG) + (C_CAST(uint64_t, MINUTES_TIME_FLAG) * UINT64_C(60)) + (C_CAST(uint64_t, HOURS_TIME_FLAG) * UINT64_C(3600)); //determine if it's timed or a range if (overwriteSeconds == 0) { - int overwriteRet = UNKNOWN; + eReturnValues overwriteRet = UNKNOWN; uint64_t localStartLBA = OVERWRITE_START_FLAG; uint64_t localRange = OVERWRITE_RANGE_FLAG; if (USE_MAX_LBA) @@ -1969,14 +2054,14 @@ int main(int argc, char *argv[]) { localRange = deviceList[deviceIter].drive_info.deviceMaxLba - localStartLBA + 1; } - overwriteRet = erase_Range(&deviceList[deviceIter], localStartLBA, localStartLBA + localRange, NULL, 0, HIDE_LBA_COUNTER); + overwriteRet = erase_Range(&deviceList[deviceIter], localStartLBA, localStartLBA + localRange, M_NULLPTR, 0, HIDE_LBA_COUNTER); switch (overwriteRet) { case SUCCESS: exitCode = 0; if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully overwrote LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Successfully overwrote LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } break; case NOT_SUPPORTED: @@ -1989,7 +2074,7 @@ int main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to erase LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Failed to erase LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -1999,8 +2084,8 @@ int main(int argc, char *argv[]) { if (overwriteSeconds > 0) { - int overwriteRet = UNKNOWN; - overwriteRet = erase_Time(&deviceList[deviceIter], OVERWRITE_START_FLAG, overwriteSeconds, NULL, 0, HIDE_LBA_COUNTER); + eReturnValues overwriteRet = UNKNOWN; + overwriteRet = erase_Time(&deviceList[deviceIter], OVERWRITE_START_FLAG, overwriteSeconds, M_NULLPTR, 0, HIDE_LBA_COUNTER); switch (overwriteRet) { case SUCCESS: @@ -2051,23 +2136,45 @@ int main(int argc, char *argv[]) { if (VERBOSITY_QUIET < toolVerbosity) { - printf("Setting MaxLBA to %"PRIu64"\n", SET_MAX_LBA_VALUE); + printf("Setting MaxLBA to %" PRIu64 "\n", SET_MAX_LBA_VALUE); + } + bool scsiAtaInSync = false; + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Setting MaxLBA to %" PRIu64 "\n", SET_MAX_LBA_VALUE); } - switch (set_Max_LBA(&deviceList[deviceIter], SET_MAX_LBA_VALUE, false)) + switch (set_Max_LBA_2(&deviceList[deviceIter], SET_MAX_LBA_VALUE, false, CHANGE_ID_STRING_FLAG)) { case SUCCESS: + scsiAtaInSync = is_Max_LBA_In_Sync_With_Adapter_Or_Driver(&deviceList[deviceIter], false); fill_Drive_Info_Data(&deviceList[deviceIter]); if (VERBOSITY_QUIET < toolVerbosity) { - double mCapacity = 0, capacity = 0; - char mCapUnits[UNIT_STRING_LENGTH] = { 0 }, capUnits[UNIT_STRING_LENGTH] = { 0 }; - char* mCapUnit = &mCapUnits[0], * capUnit = &capUnits[0]; - mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.deviceMaxLba * deviceList[deviceIter].drive_info.deviceBlockSize); + double mCapacity = 0; + double capacity = 0; + DECLARE_ZERO_INIT_ARRAY(char, mCapUnits, UNIT_STRING_LENGTH); + DECLARE_ZERO_INIT_ARRAY(char, capUnits, UNIT_STRING_LENGTH); + char* mCapUnit = &mCapUnits[0]; + char* capUnit = &capUnits[0]; + if (deviceList[deviceIter].drive_info.bridge_info.isValid) + { + mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.bridge_info.childDeviceMaxLba * deviceList[deviceIter].drive_info.bridge_info.childDeviceBlockSize); + } + else + { + mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.deviceMaxLba * deviceList[deviceIter].drive_info.deviceBlockSize); + } capacity = mCapacity; metric_Unit_Convert(&mCapacity, &mCapUnit); capacity_Unit_Convert(&capacity, &capUnit); printf("Successfully set the max LBA to %" PRIu64 "\n", SET_MAX_LBA_VALUE); printf("New Drive Capacity (%s/%s): %0.02f/%0.02f\n", mCapUnit, capUnit, mCapacity, capacity); + if (!scsiAtaInSync) + { + printf("\nWARNING: The adapter/driver/bridge is not in sync with the capacity change!\n"); + printf(" A reboot is strongly recommended to make sure the system works without\n"); + printf(" errors with the drive at its new capacity.\n\n"); + } } break; case NOT_SUPPORTED: @@ -2088,24 +2195,43 @@ int main(int argc, char *argv[]) } if (RESTORE_MAX_LBA_FLAG) { + bool scsiAtaInSync = false; if (VERBOSITY_QUIET < toolVerbosity) { printf("Restoring max LBA\n"); } - switch (set_Max_LBA(&deviceList[deviceIter], 0, true)) + switch (set_Max_LBA_2(&deviceList[deviceIter], 0, true, CHANGE_ID_STRING_FLAG)) { case SUCCESS: + scsiAtaInSync = is_Max_LBA_In_Sync_With_Adapter_Or_Driver(&deviceList[deviceIter], false); + fill_Drive_Info_Data(&deviceList[deviceIter]); if (VERBOSITY_QUIET < toolVerbosity) { - double mCapacity = 0, capacity = 0; - char mCapUnits[UNIT_STRING_LENGTH] = { 0 }, capUnits[UNIT_STRING_LENGTH] = { 0 }; - char* mCapUnit = &mCapUnits[0], * capUnit = &capUnits[0]; - mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.deviceMaxLba * deviceList[deviceIter].drive_info.deviceBlockSize); + double mCapacity = 0; + double capacity = 0; + DECLARE_ZERO_INIT_ARRAY(char, mCapUnits, UNIT_STRING_LENGTH); + DECLARE_ZERO_INIT_ARRAY(char, capUnits, UNIT_STRING_LENGTH); + char* mCapUnit = &mCapUnits[0]; + char* capUnit = &capUnits[0]; + if (deviceList[deviceIter].drive_info.bridge_info.isValid) + { + mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.bridge_info.childDeviceMaxLba * deviceList[deviceIter].drive_info.bridge_info.childDeviceBlockSize); + } + else + { + mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.deviceMaxLba * deviceList[deviceIter].drive_info.deviceBlockSize); + } capacity = mCapacity; metric_Unit_Convert(&mCapacity, &mCapUnit); capacity_Unit_Convert(&capacity, &capUnit); printf("Successfully restored the max LBA\n"); printf("New Drive Capacity (%s/%s): %0.02f/%0.02f\n", mCapUnit, capUnit, mCapacity, capacity); + if (!scsiAtaInSync) + { + printf("\nWARNING: The adapter/driver/bridge is not in sync with the capacity change!\n"); + printf(" A reboot is strongly recommended to make sure the system works without\n"); + printf(" errors with the drive at its new capacity.\n\n"); + } } break; case NOT_SUPPORTED: @@ -2125,9 +2251,9 @@ int main(int argc, char *argv[]) } } - if (PROGRESS_CHAR != NULL) + if (PROGRESS_CHAR != M_NULLPTR) { - int result = UNKNOWN; + eReturnValues result = UNKNOWN; //first take whatever was entered in progressTest and convert it to uppercase to do fewer string comparisons convert_String_To_Upper_Case(progressTest); //do some string comparisons to figure out what we are checking for progress on @@ -2169,7 +2295,7 @@ int main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -2227,11 +2353,14 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s 1000 --%s 2000\n", util_name, deviceHandleExample, TRIM_LONG_OPT_STRING, TRIM_RANGE_LONG_OPT_STRING); printf("\t%s -d %s --%s 134217728\n", util_name, deviceHandleExample, PROVISION_LONG_OPT_STRING); printf("\t%s -d %s --%s 134217728\n", util_name, deviceHandleExample, SET_MAX_LBA_LONG_OPT_STRING); + printf("\t%s -d %s --%s 134217728 --%s\n", util_name, deviceHandleExample, SET_MAX_LBA_LONG_OPT_STRING, CHANGE_ID_STRING_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, RESTORE_MAX_LBA_LONG_OPT_STRING); + printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT_STRING); + //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -2276,6 +2405,8 @@ void utility_Usage(bool shortUsage) print_Test_Unit_Ready_Help(shortUsage); //utility tests/operations go here - alphabetized print_Fast_Discovery_Help(shortUsage); + print_Capacity_Model_Number_Mapping_Help(shortUsage); + print_Change_Id_String_Help(shortUsage); print_Check_Power_Mode_Help(shortUsage); print_Display_LBA_Help(shortUsage); print_Firmware_Activate_Help(shortUsage); diff --git a/utils/C/openSeaChest/openSeaChest_Configure.c b/utils/C/openSeaChest/openSeaChest_Configure.c index 2a471c82..ef5c5768 100644 --- a/utils/C/openSeaChest/openSeaChest_Configure.c +++ b/utils/C/openSeaChest/openSeaChest_Configure.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,26 +15,31 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "secure_file.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" #include "operations.h" +#include "power_control.h"//PUIS. transitions users to using openSeaChest_PowerControl for this feature. #include "drive_info.h" #include "set_max_lba.h" #include "trim_unmap.h" #include "smart.h" #include "logs.h" #include "ata_device_config_overlay.h" +#include "power_control.h" //////////////////////// // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Configure"; -const char *buildVersion = "2.5.0"; +const char *buildVersion = "2.7.1"; //////////////////////////// // functions to declare // @@ -53,16 +59,18 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR + CAPACITY_MODEL_NUMBER_MAPPING_VAR + CHANGE_ID_STRING_VAR SAT_INFO_VAR DATA_ERASE_VAR POSSIBLE_DATA_ERASE_VAR @@ -107,6 +115,7 @@ int32_t main(int argc, char *argv[]) #endif SCT_ERROR_RECOVERY_CONTROL_VARS FREE_FALL_VARS + WRV_VARS SCSI_MP_RESET_VARS SCSI_MP_RESTORE_VARS @@ -132,6 +141,8 @@ int32_t main(int argc, char *argv[]) DEVICE_LONG_OPT, HELP_LONG_OPT, DEVICE_INFO_LONG_OPT, + CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT, + CHANGE_ID_STRING_LONG_OPT, SAT_INFO_LONG_OPT, USB_CHILD_INFO_LONG_OPT, SCAN_LONG_OPT, @@ -188,6 +199,7 @@ int32_t main(int argc, char *argv[]) ATA_DCO_SETMAXLBA_LONG_OPT, ATA_DCO_SETMAXMODE_LONG_OPT, ATA_DCO_DISABLE_FEEATURES_LONG_OPT, + WRV_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -226,11 +238,11 @@ int32_t main(int argc, char *argv[]) //parse long options that have no short option and required arguments here if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { - if (strlen(optarg) == strlen(DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, DATA_ERASE_ACCEPT_STRING, strlen(DATA_ERASE_ACCEPT_STRING)) == 0) + if (strcmp(optarg, DATA_ERASE_ACCEPT_STRING) == 0) { DATA_ERASE_FLAG = true; } - else if (strlen(optarg) == strlen(POSSIBLE_DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, POSSIBLE_DATA_ERASE_ACCEPT_STRING, strlen(POSSIBLE_DATA_ERASE_ACCEPT_STRING)) == 0) + else if (strcmp(optarg, POSSIBLE_DATA_ERASE_ACCEPT_STRING) == 0) { POSSIBLE_DATA_ERASE_FLAG = true; } @@ -240,9 +252,9 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SET_MAX_LBA_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_MAX_LBA_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_MAX_LBA_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &SET_MAX_LBA_VALUE)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &SET_MAX_LBA_VALUE)) { SET_MAX_LBA_FLAG = true; } @@ -252,17 +264,31 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SET_PHY_SPEED_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_PHY_SPEED_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_PHY_SPEED_LONG_OPT_STRING) == 0) { - SET_PHY_SPEED_FLAG = true; - SET_PHY_SPEED_GEN = C_CAST(uint8_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_PHY_SPEED_GEN) && SET_PHY_SPEED_GEN < SET_PHY_SPEED_MAX_GENERATION) + { + SET_PHY_SPEED_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(SET_PHY_SPEED_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp(longopts[optionIndex].name, SET_PHY_SAS_PHY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_PHY_SAS_PHY_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_PHY_SAS_PHY_LONG_OPT_STRING) == 0) { - SET_PHY_ALL_PHYS = false; - SET_PHY_SAS_PHY_IDENTIFIER = C_CAST(uint8_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_PHY_SAS_PHY_IDENTIFIER)) + { + SET_PHY_ALL_PHYS = false; + } + else + { + print_Error_In_Cmd_Line_Args(SET_PHY_SAS_PHY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if ((strncmp(longopts[optionIndex].name, SET_READY_LED_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_READY_LED_LONG_OPT_STRING))) == 0)) + else if ((strcmp(longopts[optionIndex].name, SET_READY_LED_LONG_OPT_STRING) == 0)) { if (strcmp(optarg, "default") == 0) { @@ -289,7 +315,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, NV_CACHE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(NV_CACHE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, NV_CACHE_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "info") == 0) { @@ -313,7 +339,7 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, READ_LOOK_AHEAD_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(READ_LOOK_AHEAD_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, READ_LOOK_AHEAD_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "info") == 0) { @@ -337,7 +363,7 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, WRITE_CACHE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(WRITE_CACHE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, WRITE_CACHE_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "info") == 0) { @@ -361,9 +387,9 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, PROVISION_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(PROVISION_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, PROVISION_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &SET_MAX_LBA_VALUE)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &SET_MAX_LBA_VALUE)) { SET_MAX_LBA_FLAG = true; //now, based on the new MaxLBA, set the TRIM/UNMAP start flag to get rid of the LBAs that will not be above the new maxLBA (the range will be set later) @@ -375,7 +401,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, LOW_CURRENT_SPINUP_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(LOW_CURRENT_SPINUP_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, LOW_CURRENT_SPINUP_LONG_OPT_STRING) == 0) { LOW_CURRENT_SPINUP_FLAG = true; if (strcmp(optarg, "low") == 0) @@ -455,13 +481,23 @@ int32_t main(int argc, char *argv[]) else if (strcmp(longopts[optionIndex].name, PUIS_FEATURE_LONG_OPT_STRING) == 0) { PUIS_FEATURE_FLAG = true; - if (strcmp(optarg, "enable") == 0) + if (strcmp(optarg, "info") == 0) + { + PUIS_FEATURE_INFO_FLAG = true; + } + else if (strcmp(optarg, "enable") == 0) { PUIS_FEATURE_STATE_FLAG = true; + PUIS_STATE_VALID_FLAG = true; } else if (strcmp(optarg, "disable") == 0) { PUIS_FEATURE_STATE_FLAG = false; + PUIS_STATE_VALID_FLAG = true; + } + else if (strcmp(optarg, "spinup") == 0) + { + PUIS_FEATURE_SPINUP_FLAG = true; } else { @@ -509,26 +545,43 @@ int32_t main(int argc, char *argv[]) } else { - uint32_t multiplier = 100;//100 millisecond conversion - //first check is a unit is provided. - if (strstr(optarg, "ms")) - { - multiplier = UINT32_C(1); - } - else if (strstr(optarg, "s")) - { - multiplier = UINT32_C(1000); - } - else if (strstr(optarg, "m")) + uint32_t multiplier = UINT32_C(100);//100 millisecond conversion + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &SCT_ERROR_RECOVERY_CONTROL_READ_TIMER_VALUE)) { - multiplier = UINT32_C(60000); + //first check is a unit is provided. + if (unit) + { + if (strcmp(unit, "ms") == 0) + { + multiplier = UINT32_C(1); + } + else if (strcmp(unit, "s") == 0) + { + multiplier = UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + multiplier = UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + multiplier = UINT32_C(3600000); + } + else + { + print_Error_In_Cmd_Line_Args(SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + SCT_ERROR_RECOVERY_CONTROL_SET_READ_TIMER = true; + SCT_ERROR_RECOVERY_CONTROL_READ_TIMER_VALUE *= multiplier; } - else if (strstr(optarg, "h")) + else { - multiplier = UINT32_C(3600000); + print_Error_In_Cmd_Line_Args(SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - SCT_ERROR_RECOVERY_CONTROL_SET_READ_TIMER = true; - SCT_ERROR_RECOVERY_CONTROL_READ_TIMER_VALUE = C_CAST(uint32_t, atoi(optarg) * multiplier); } } else if (strcmp(longopts[optionIndex].name, SCT_ERROR_RECOVERY_CONTROL_WRITE_LONG_OPT_STRING) == 0) @@ -543,26 +596,43 @@ int32_t main(int argc, char *argv[]) } else { - uint32_t multiplier = 100;//100 millisecond conversion - //first check is a unit is provided. - if (strstr(optarg, "ms")) - { - multiplier = UINT32_C(1); - } - else if (strstr(optarg, "s")) + uint32_t multiplier = UINT32_C(100);//100 millisecond conversion + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &SCT_ERROR_RECOVERY_CONTROL_READ_TIMER_VALUE)) { - multiplier = UINT32_C(1000); - } - else if (strstr(optarg, "m")) - { - multiplier = UINT32_C(60000); + //first check is a unit is provided. + if (unit) + { + if (strcmp(unit, "ms") == 0) + { + multiplier = UINT32_C(1); + } + else if (strcmp(unit, "s") == 0) + { + multiplier = UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + multiplier = UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + multiplier = UINT32_C(3600000); + } + else + { + print_Error_In_Cmd_Line_Args(SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + SCT_ERROR_RECOVERY_CONTROL_SET_WRITE_TIMER = true; + SCT_ERROR_RECOVERY_CONTROL_WRITE_TIMER_VALUE *=multiplier; } - else if (strstr(optarg, "h")) + else { - multiplier = UINT32_C(3600000); + print_Error_In_Cmd_Line_Args(SCT_ERROR_RECOVERY_CONTROL_READ_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - SCT_ERROR_RECOVERY_CONTROL_SET_WRITE_TIMER = true; - SCT_ERROR_RECOVERY_CONTROL_WRITE_TIMER_VALUE = C_CAST(uint32_t, atoi(optarg) * multiplier); } } else if (strcmp(longopts[optionIndex].name, FREE_FALL_LONG_OPT_STRING) == 0) @@ -578,57 +648,66 @@ int32_t main(int argc, char *argv[]) } else { - uint64_t value = 0; //this is a value to read in. - if (get_And_Validate_Integer_Input(optarg, &value)) + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FREE_FALL_SENSITIVITY)) { print_Error_In_Cmd_Line_Args(FREE_FALL_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - if (value > UINT8_MAX) + else { - print_Error_In_Cmd_Line_Args(FREE_FALL_LONG_OPT_STRING, optarg); - exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + FREE_FALL_FLAG = true; } - FREE_FALL_FLAG = true; - FREE_FALL_SENSITIVITY = C_CAST(uint8_t, value); } } else if (strcmp(longopts[optionIndex].name, SCSI_MP_RESET_LONG_OPT_STRING) == 0) { SCSI_MP_RESET_OP = true; - char * token = strtok(optarg, "-"); + char *saveptr = M_NULLPTR; + rsize_t duplen = 0; + char* dupoptarg = strdup(optarg); + char * token = M_NULLPTR; uint8_t count = 0; bool errorInCL = false; + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + token = common_String_Token(dupoptarg, &duplen, "-", &saveptr); + } + else + { + errorInCL = true; + } while (token && !errorInCL && count < 2) { - uint64_t value = 0; - if (get_And_Validate_Integer_Input(token, &value)) + uint8_t value = 0; + if (get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &value)) { switch (count) { case 0: - SCSI_MP_RESET_PAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_MP_RESET_PAGE_NUMBER = value; if (value > MP_RETURN_ALL_PAGES) { errorInCL = true; } break; case 1: - SCSI_MP_RESET_SUBPAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_MP_RESET_SUBPAGE_NUMBER = value; break; default: errorInCL = true; break; } ++count; - token = strtok(NULL, "-"); + token = common_String_Token(M_NULLPTR, &duplen, "-", &saveptr); } else { errorInCL = true; } } + safe_free(&dupoptarg); if (errorInCL) { print_Error_In_Cmd_Line_Args(SCSI_MP_RESET_LONG_OPT_STRING, optarg); @@ -638,38 +717,51 @@ int32_t main(int argc, char *argv[]) else if (strcmp(longopts[optionIndex].name, SCSI_MP_RESTORE_LONG_OPT_STRING) == 0) { SCSI_MP_RESTORE_OP = true; - char * token = strtok(optarg, "-"); + char *saveptr = M_NULLPTR; + rsize_t duplen = 0; + char* dupoptarg = strdup(optarg); + char * token = M_NULLPTR; uint8_t count = 0; bool errorInCL = false; + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + token = common_String_Token(dupoptarg, &duplen, "-", &saveptr); + } + else + { + errorInCL = true; + } while (token && !errorInCL && count < 2) { - uint64_t value = 0; - if (get_And_Validate_Integer_Input(token, &value)) + uint8_t value = 0; + if (get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &value)) { switch (count) { case 0: - SCSI_MP_RESTORE_PAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_MP_RESTORE_PAGE_NUMBER = value; if (value > MP_RETURN_ALL_PAGES) { errorInCL = true; } break; case 1: - SCSI_MP_RESTORE_SUBPAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_MP_RESTORE_SUBPAGE_NUMBER = value; break; default: errorInCL = true; break; } ++count; - token = strtok(NULL, "-"); + token = common_String_Token(M_NULLPTR, &duplen, "-", &saveptr); } else { errorInCL = true; } } + safe_free(&dupoptarg); if (errorInCL) { print_Error_In_Cmd_Line_Args(SCSI_MP_RESTORE_LONG_OPT_STRING, optarg); @@ -679,38 +771,51 @@ int32_t main(int argc, char *argv[]) else if (strcmp(longopts[optionIndex].name, SCSI_MP_SAVE_LONG_OPT_STRING) == 0) { SCSI_MP_SAVE_OP = true; - char * token = strtok(optarg, "-"); + char *saveptr = M_NULLPTR; + rsize_t duplen = 0; + char* dupoptarg = strdup(optarg); + char * token = M_NULLPTR; uint8_t count = 0; bool errorInCL = false; + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + token = common_String_Token(dupoptarg, &duplen, "-", &saveptr); + } + else + { + errorInCL = true; + } while (token && !errorInCL && count < 2) { - uint64_t value = 0; - if (get_And_Validate_Integer_Input(token, &value)) + uint8_t value = 0; + if (get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &value)) { switch (count) { case 0: - SCSI_MP_SAVE_PAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_MP_SAVE_PAGE_NUMBER = value; if (value > MP_RETURN_ALL_PAGES) { errorInCL = true; } break; case 1: - SCSI_MP_SAVE_SUBPAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_MP_SAVE_SUBPAGE_NUMBER = value; break; default: errorInCL = true; break; } ++count; - token = strtok(NULL, "-"); + token = common_String_Token(M_NULLPTR, &duplen, "-", &saveptr); } else { errorInCL = true; } } + safe_free(&dupoptarg); if (errorInCL) { print_Error_In_Cmd_Line_Args(SCSI_MP_SAVE_LONG_OPT_STRING, optarg); @@ -720,38 +825,51 @@ int32_t main(int argc, char *argv[]) else if (strcmp(longopts[optionIndex].name, SCSI_SHOW_MP_LONG_OPT_STRING) == 0) { SCSI_SHOW_MP_OP = true; - char * token = strtok(optarg, "-"); + char *saveptr = M_NULLPTR; + rsize_t duplen = 0; + char* dupoptarg = strdup(optarg); + char * token = M_NULLPTR; uint8_t count = 0; bool errorInCL = false; + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + token = common_String_Token(dupoptarg, &duplen, "-", &saveptr); + } + else + { + errorInCL = true; + } while (token && !errorInCL && count < 2) { - uint64_t value = 0; - if (get_And_Validate_Integer_Input(token, &value)) + uint8_t value = 0; + if (get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &value)) { switch (count) { case 0: - SCSI_SHOW_MP_PAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_SHOW_MP_PAGE_NUMBER = value; if (value > MP_RETURN_ALL_PAGES) { errorInCL = true; } break; case 1: - SCSI_SHOW_MP_SUBPAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_SHOW_MP_SUBPAGE_NUMBER = value; break; default: errorInCL = true; break; } ++count; - token = strtok(NULL, "-"); + token = common_String_Token(M_NULLPTR, &duplen, "-", &saveptr); } else { errorInCL = true; } } + safe_free(&dupoptarg); if (errorInCL) { print_Error_In_Cmd_Line_Args(SCSI_SHOW_MP_LONG_OPT_STRING, optarg); @@ -762,92 +880,108 @@ int32_t main(int argc, char *argv[]) { SCSI_SET_MP_OP = true; //first check if they are specifying a file! - if (strncmp(optarg, "file", 4) == 0) + if (strncmp(optarg, "file=", 5) == 0) { //format is file=filename.txt - int sscanfRes = sscanf(optarg, SCSI_SET_MP_SSCANF_FILE_FORMAT_STR , SCSI_SET_MP_FILENAME); - if (sscanfRes < 1 || sscanfRes == EOF) - { - print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); - exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); - } - else + char *filenameptr = strstr(optarg, "="); + if (filenameptr && safe_strlen(filenameptr) > 1) { - if (!os_File_Exists(SCSI_SET_MP_FILENAME)) + filenameptr += 1;//go past the = + if (snprintf(SCSI_SET_MP_FILENAME, SCSI_SET_MP_FILENAME_LEN, "%s", filenameptr) <= 0) { - //TODO: print file open error instead??? print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); - exit(UTIL_EXIT_CANNOT_OPEN_FILE); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - //else we open the file later to use + } + else + { + print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } else { //formatted as mp[-sp]:byte:highbit:fieldWidth=value - #define PARSE_MP_PAGE_AND_SUBPAGE_LENGTH 8 - char pageAndSubpage[PARSE_MP_PAGE_AND_SUBPAGE_LENGTH] = { 0 }; - char *token = strtok(optarg, ":="); - uint8_t tokenCounter = 0; - while (token && tokenCounter < 5) - { - //go through each string and convert it from a string into a value we can use in this tool - //start with page and subpage - switch (tokenCounter) - { - case 0://page-subpage +#define PARSE_MP_PAGE_AND_SUBPAGE_LENGTH 8 + DECLARE_ZERO_INIT_ARRAY(char, pageAndSubpage, PARSE_MP_PAGE_AND_SUBPAGE_LENGTH); + char *saveptr = M_NULLPTR; + rsize_t duplen = 0; + char *dupoptarg = strdup(optarg); + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + char *token = common_String_Token(dupoptarg, &duplen, ":=", &saveptr); + uint8_t tokenCounter = 0; + while (token && tokenCounter < 5) { - snprintf(pageAndSubpage, PARSE_MP_PAGE_AND_SUBPAGE_LENGTH, "%s", token); - //parse later outside this loop. If we use strtok again in here, we'll break the way the parsing works... :( - } - break; - case 1://byte - SCSI_SET_MP_BYTE = C_CAST(uint16_t, atoi(token)); - break; - case 2://bit - if (atoi(token) > 7) + //go through each string and convert it from a string into a value we can use in this tool + //start with page and subpage + switch (tokenCounter) { - print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); - exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); - } - SCSI_SET_MP_BIT = C_CAST(uint8_t, atoi(token)); - break; - case 3://field width - if (atoi(token) > 64) + case 0://page-subpage { - print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); - exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + snprintf(pageAndSubpage, PARSE_MP_PAGE_AND_SUBPAGE_LENGTH, "%s", token); + //parse later outside this loop. If we tokenize again in here, we'll break the way the parsing works... :( } - SCSI_SET_MP_FIELD_LEN_BITS = C_CAST(uint8_t, atoi(token)); break; - case 4://value - if (!get_And_Validate_Integer_Input(token, &SCSI_SET_MP_FIELD_VALUE)) - { - print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); - exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + case 1://byte + if (!get_And_Validate_Integer_Input_Uint16(token, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_SET_MP_BYTE)) + { + print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + break; + case 2://bit + if (!get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_SET_MP_BIT) && SCSI_SET_MP_BIT > 7) + { + print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + break; + case 3://field width + if (!get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_SET_MP_FIELD_LEN_BITS) && SCSI_SET_MP_FIELD_LEN_BITS > 64) + { + print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + break; + case 4://value + if (!get_And_Validate_Integer_Input_Uint64(token, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_SET_MP_FIELD_VALUE)) + { + print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + break; + default: + //shouldn't get here!!! throw an error?! + break; } - break; - default: - //shouldn't get here!!! throw an error?! - break; + ++tokenCounter; + token = common_String_Token(M_NULLPTR, &duplen, ":=", &saveptr); } - ++tokenCounter; - token = strtok(NULL, ":="); } - char *pagetoken = strtok(pageAndSubpage, "-"); + else + { + print_Error_In_Cmd_Line_Args(SCSI_SET_MP_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + safe_free(&dupoptarg); + saveptr = M_NULLPTR; + rsize_t pageSPlen = safe_strlen(pageAndSubpage); + char *pagetoken = common_String_Token(pageAndSubpage, &pageSPlen, "-", &saveptr); if (pagetoken) { - SCSI_SET_MP_PAGE_NUMBER = C_CAST(uint8_t, strtoul(pagetoken, NULL, 16)); - pagetoken = strtok(NULL, "-"); + SCSI_SET_MP_PAGE_NUMBER = C_CAST(uint8_t, strtoul(pagetoken, M_NULLPTR, 16)); + pagetoken = common_String_Token(M_NULLPTR, &pageSPlen, "-", &saveptr); if (pagetoken) { - SCSI_SET_MP_SUBPAGE_NUMBER = C_CAST(uint8_t, strtoul(pagetoken, NULL, 16)); + SCSI_SET_MP_SUBPAGE_NUMBER = C_CAST(uint8_t, strtoul(pagetoken, M_NULLPTR, 16)); } } - else //should this be an error condition since strtok failed? + else //should this be an error condition since tokenize failed? { //no subpage - SCSI_SET_MP_PAGE_NUMBER = C_CAST(uint8_t, strtoul(pageAndSubpage, NULL, 16)); + SCSI_SET_MP_PAGE_NUMBER = C_CAST(uint8_t, strtoul(pageAndSubpage, M_NULLPTR, 16)); SCSI_SET_MP_SUBPAGE_NUMBER = 0; } if (SCSI_SET_MP_PAGE_NUMBER > 0x3F) @@ -927,38 +1061,51 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, SCSI_RESET_LP_PAGE_LONG_OPT_STRING) == 0) { - char * token = strtok(optarg, "-"); + char *saveptr = M_NULLPTR; + rsize_t duplen = 0; + char* dupoptarg = strdup(optarg); + char * token = M_NULLPTR; uint8_t count = 0; bool errorInCL = false; + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + token = common_String_Token(dupoptarg, &duplen, "-", &saveptr); + } + else + { + errorInCL = true; + } while (token && !errorInCL && count < 2) { - uint64_t value = 0; - if (get_And_Validate_Integer_Input(token, &value)) + uint8_t value = 0; + if (get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &value)) { switch (count) { case 0: - SCSI_RESET_LP_PAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_RESET_LP_PAGE_NUMBER = value; if (value > 0x3F) { errorInCL = true; } break; case 1: - SCSI_RESET_LP_SUBPAGE_NUMBER = C_CAST(uint8_t, value); + SCSI_RESET_LP_SUBPAGE_NUMBER = value; break; default: errorInCL = true; break; } ++count; - token = strtok(NULL, "-"); + token = common_String_Token(M_NULLPTR, &duplen, "-", &saveptr); } else { errorInCL = true; } } + safe_free(&dupoptarg); if (errorInCL) { print_Error_In_Cmd_Line_Args(SCSI_RESET_LP_PAGE_LONG_OPT_STRING, optarg); @@ -967,11 +1114,9 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, ATA_DCO_SETMAXLBA_LONG_OPT_STRING) == 0) { - uint64_t dcoMaxLBA = 0; - if (get_And_Validate_Integer_Input(optarg, &dcoMaxLBA)) + if (get_And_Validate_Integer_Input_Uint64(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &ATA_DCO_SETMAXLBA_VALUE)) { ATA_DCO_SETMAXLBA = true; - ATA_DCO_SETMAXLBA_VALUE = dcoMaxLBA; } else { @@ -1039,7 +1184,9 @@ int32_t main(int argc, char *argv[]) char* dcoDisableFeatList = strdup(optarg); if (dcoDisableFeatList) { - char* dcoFeatToken = strtok(dcoDisableFeatList, ","); + char *saveptr = M_NULLPTR; + rsize_t featlistlen = safe_strlen(dcoDisableFeatList); + char* dcoFeatToken = common_String_Token(dcoDisableFeatList, &featlistlen, ",", &saveptr); ATA_DCO_DISABLE_FEATURES = true; while (dcoFeatToken) { @@ -1155,14 +1302,14 @@ int32_t main(int argc, char *argv[]) else { //error, unknown option - safe_Free(dcoDisableFeatList) + safe_free(&dcoDisableFeatList); ATA_DCO_DISABLE_FEATURES = false; print_Error_In_Cmd_Line_Args(ATA_DCO_DISABLE_FEEATURES_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - dcoFeatToken = strtok(NULL, ","); + dcoFeatToken = common_String_Token(M_NULLPTR, &featlistlen, ",", &saveptr); } - safe_Free(dcoDisableFeatList) + safe_free(&dcoDisableFeatList); } else { @@ -1171,22 +1318,53 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, WRV_LONG_OPT_STRING) == 0) + { + if (strcmp(optarg, "info") == 0) + { + WRV_INFO = true; + } + else if (strcmp(optarg, "all") == 0) + { + WRV_FLAG = true; + WRV_ALL = true; + } + else if (strcmp(optarg, "vendor") == 0) + { + WRV_FLAG = true; + WRV_VENDOR = true; + } + else if (strcmp(optarg, "disable") == 0) + { + WRV_FLAG = true; + WRV_DISABLE = true; + } + else if (get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &WRV_USER_VALUE)) + { + WRV_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(WRV_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -1255,9 +1433,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -1294,7 +1473,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -1391,7 +1570,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -1447,6 +1626,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -1468,6 +1649,7 @@ int32_t main(int argc, char *argv[]) || TEST_UNIT_READY_FLAG || LOWLEVEL_INFO_FLAG //check for other tool specific options here + || CAPACITY_MODEL_NUMBER_MAPPING_FLAG || RESTORE_MAX_LBA_FLAG || SET_MAX_LBA_FLAG || SET_PHY_SPEED_FLAG @@ -1508,6 +1690,8 @@ int32_t main(int argc, char *argv[]) || ATA_DCO_IDENTIFY || ATA_DCO_FREEZE || ATA_DCO_RESTORE + || WRV_FLAG + || WRV_INFO )) { utility_Usage(true); @@ -1516,7 +1700,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1559,7 +1743,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -1607,11 +1791,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -1635,7 +1819,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -1677,7 +1861,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1702,7 +1886,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1742,6 +1926,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1802,6 +1995,35 @@ int32_t main(int argc, char *argv[]) show_Test_Unit_Ready_Status(&deviceList[deviceIter]); } + if (CAPACITY_MODEL_NUMBER_MAPPING_FLAG) + { + if (is_Change_Identify_String_Supported(&deviceList[deviceIter])) + { + ptrcapacityModelNumberMapping capModelMap = get_Capacity_Model_Number_Mapping(&deviceList[deviceIter]); + if (capModelMap) + { + print_Capacity_Model_Number_Mapping(capModelMap); + delete_Capacity_Model_Number_Mapping(capModelMap); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to get Capacity / Model Number Mapping\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Capacity / Model Number Mapping not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } + } + if (SCSI_SHOW_MP_OP) { if (SCSI_SHOW_MP_MPC_VALUE > 3) @@ -1812,7 +2034,7 @@ int32_t main(int argc, char *argv[]) else { //show the specific MPC value - show_SCSI_Mode_Page(&deviceList[deviceIter], SCSI_SHOW_MP_PAGE_NUMBER, SCSI_SHOW_MP_SUBPAGE_NUMBER, SCSI_SHOW_MP_MPC_VALUE, SCSI_SHOW_MP_BUFFER_MODE); + show_SCSI_Mode_Page(&deviceList[deviceIter], SCSI_SHOW_MP_PAGE_NUMBER, SCSI_SHOW_MP_SUBPAGE_NUMBER, C_CAST(eScsiModePageControl, SCSI_SHOW_MP_MPC_VALUE), SCSI_SHOW_MP_BUFFER_MODE); } } @@ -1820,7 +2042,7 @@ int32_t main(int argc, char *argv[]) { dcoData dco; memset(&dco, 0, sizeof(dcoData)); - switch(dco_Identify(&deviceList[deviceIter], &dco)) + switch (dco_Identify(&deviceList[deviceIter], &dco)) { case SUCCESS: show_DCO_Identify_Data(&dco); @@ -1939,34 +2161,34 @@ int32_t main(int argc, char *argv[]) { case 10://udma6 dco.udma.udma6 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 9://udma5 dco.udma.udma5 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 8://udma4 dco.udma.udma4 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 7://udma3 dco.udma.udma3 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 6://udma2 dco.udma.udma2 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 5://udma1 dco.udma.udma1 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 4://udma0 dco.udma.udma0 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 3://mwdma2 dco.mwdma.mwdma2 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 2://mwdma1 dco.mwdma.mwdma1 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 1://mwdma0 dco.mwdma.mwdma0 = true; - M_FALLTHROUGH + M_FALLTHROUGH; case 0://no DMA modes at all break; } @@ -2271,7 +2493,7 @@ int32_t main(int argc, char *argv[]) if (SET_SSC_FLAG) { - switch (set_SSC_Feature_SATA(&deviceList[deviceIter], SSC_MODE)) + switch (set_SSC_Feature_SATA(&deviceList[deviceIter], C_CAST(eSSCFeatureState, SSC_MODE))) { case SUCCESS: printf("Successfully set SSC feature to "); @@ -2466,7 +2688,6 @@ int32_t main(int argc, char *argv[]) { uint16_t sctFlags = 0; uint16_t state = 0; - //TODO: switch to sct_Get_Feature_Control since it is the correct call to use for this info if (SUCCESS == sct_Get_Feature_Control(&deviceList[deviceIter], SCT_FEATURE_CONTROL_WRITE_CACHE_STATE, &SCT_WRITE_CACHE_SETTING, &SCT_WRITE_CACHE_SET_DEFAULT, &state, &sctFlags)) { if (state == 0 || state > 0x0003) @@ -2582,7 +2803,6 @@ int32_t main(int argc, char *argv[]) { uint16_t sctFlags = 0; uint16_t state = 0; - //TODO: switch to sct_Get_Feature_Control since it is the correct call to use for this info if (SUCCESS == sct_Get_Feature_Control(&deviceList[deviceIter], SCT_FEATURE_CONTROL_WRITE_CACHE_REORDERING, &SCT_WRITE_CACHE_REORDER_SETTING, &SCT_WRITE_CACHE_REORDER_SET_DEFAULT, &state, &sctFlags)) { if (state == 0 || state > 0x0002) @@ -3123,7 +3343,7 @@ int32_t main(int argc, char *argv[]) case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully trimmed/unmapped LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Successfully trimmed/unmapped LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } break; case NOT_SUPPORTED: @@ -3136,7 +3356,7 @@ int32_t main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to trim/unmap LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Failed to trim/unmap LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -3168,18 +3388,21 @@ int32_t main(int argc, char *argv[]) bool scsiAtaInSync = false; if (VERBOSITY_QUIET < toolVerbosity) { - printf("Setting MaxLBA to %"PRIu64"\n", SET_MAX_LBA_VALUE); + printf("Setting MaxLBA to %" PRIu64 "\n", SET_MAX_LBA_VALUE); } - switch (set_Max_LBA(&deviceList[deviceIter], SET_MAX_LBA_VALUE, false)) + switch (set_Max_LBA_2(&deviceList[deviceIter], SET_MAX_LBA_VALUE, false, CHANGE_ID_STRING_FLAG)) { case SUCCESS: scsiAtaInSync = is_Max_LBA_In_Sync_With_Adapter_Or_Driver(&deviceList[deviceIter], false); fill_Drive_Info_Data(&deviceList[deviceIter]); if (VERBOSITY_QUIET < toolVerbosity) { - double mCapacity = 0, capacity = 0; - char mCapUnits[UNIT_STRING_LENGTH] = { 0 }, capUnits[UNIT_STRING_LENGTH] = { 0 }; - char* mCapUnit = &mCapUnits[0], * capUnit = &capUnits[0]; + double mCapacity = 0; + double capacity = 0; + DECLARE_ZERO_INIT_ARRAY(char, mCapUnits, UNIT_STRING_LENGTH); + DECLARE_ZERO_INIT_ARRAY(char, capUnits, UNIT_STRING_LENGTH); + char* mCapUnit = &mCapUnits[0]; + char* capUnit = &capUnits[0]; if (deviceList[deviceIter].drive_info.bridge_info.isValid) { mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.bridge_info.childDeviceMaxLba * deviceList[deviceIter].drive_info.bridge_info.childDeviceBlockSize); @@ -3224,16 +3447,19 @@ int32_t main(int argc, char *argv[]) { printf("Restoring max LBA\n"); } - switch (set_Max_LBA(&deviceList[deviceIter], 0, true)) + switch (set_Max_LBA_2(&deviceList[deviceIter], 0, true, CHANGE_ID_STRING_FLAG)) { case SUCCESS: scsiAtaInSync = is_Max_LBA_In_Sync_With_Adapter_Or_Driver(&deviceList[deviceIter], false); fill_Drive_Info_Data(&deviceList[deviceIter]); if (VERBOSITY_QUIET < toolVerbosity) { - double mCapacity = 0, capacity = 0; - char mCapUnits[UNIT_STRING_LENGTH] = { 0 }, capUnits[UNIT_STRING_LENGTH] = { 0 }; - char* mCapUnit = &mCapUnits[0], * capUnit = &capUnits[0]; + double mCapacity = 0; + double capacity = 0; + DECLARE_ZERO_INIT_ARRAY(char, mCapUnits, UNIT_STRING_LENGTH); + DECLARE_ZERO_INIT_ARRAY(char, capUnits, UNIT_STRING_LENGTH); + char* mCapUnit = &mCapUnits[0]; + char* capUnit = &capUnits[0]; if (deviceList[deviceIter].drive_info.bridge_info.isValid) { mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.bridge_info.childDeviceMaxLba * deviceList[deviceIter].drive_info.bridge_info.childDeviceBlockSize); @@ -3324,51 +3550,158 @@ int32_t main(int argc, char *argv[]) } } - if(PUIS_FEATURE_FLAG) + if (PUIS_FEATURE_FLAG) { - switch (enable_Disable_PUIS_Feature(&deviceList[deviceIter], PUIS_FEATURE_STATE_FLAG)) + printf("\nPlease switch use of PUIS options to openSeaChest_PowerControl.\n"); + printf("These options will be removed from openSeaChest_Configure in a future release.\n"); + puisInfo info; + memset(&info, 0, sizeof(puisInfo)); + eReturnValues puisInfoRet = get_PUIS_Info(&deviceList[deviceIter], &info); + if (PUIS_FEATURE_SPINUP_FLAG) { - case SUCCESS: - if (VERBOSITY_QUIET < toolVerbosity) + if (info.puisEnabled) { - if (PUIS_FEATURE_STATE_FLAG) + switch (puis_Spinup(&deviceList[deviceIter])) { - printf("PUIS feature successfully enabled!\n"); + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\nSuccessfully performed PUIS spinup command\n"); + printf("\nHint:Use --checkPowerMode option to check the new Power State.\n\n"); + } + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("PUIS spinup command is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to perform the PUIS spinup command\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + else + { + if (info.puisSupported) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("PUIS feature is not enabled. Nothing to do.\n"); + } } else { - printf("PUIS feature successfully disabled!\n"); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("PUIS spinup command is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; } } - break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) + } + if (PUIS_FEATURE_INFO_FLAG) + { + switch (puisInfoRet) { - if (PUIS_FEATURE_STATE_FLAG) + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) { - printf("Enabling PUIS feature not supported on this device.\n"); + printf("===PUIS Info===\n"); + if (info.puisSupported) + { + if (info.puisEnabled) + { + printf("\tPUIS is supported and enabled\n"); + } + else + { + printf("\tPUIS is supported\n"); + } + if (info.spinupCommandRequired) + { + printf("\tSpin-Up command is required for medium access.\n"); + } + else + { + printf("\tAutomatic spin-up as needed for medium access.\n"); + } + } + else + { + printf("\tPUIS is not supported on this device.\n"); + } } - else + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("PUIS is not available on this device type!\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) { - printf("Disabling PUIS feature not supported on this device.\n"); + printf("Failed to get PUIS info from this device\n"); } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; - break; - default: - if (VERBOSITY_QUIET < toolVerbosity) + } + if (PUIS_STATE_VALID_FLAG) + { + switch (enable_Disable_PUIS_Feature(&deviceList[deviceIter], PUIS_FEATURE_STATE_FLAG)) { - if (PUIS_FEATURE_STATE_FLAG) + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to enable PUIS feature!\n"); + if (PUIS_FEATURE_STATE_FLAG) + { + printf("PUIS feature successfully enabled!\n"); + } + else + { + printf("PUIS feature successfully disabled!\n"); + } } - else + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to disable PUIS feature!\n"); + if (PUIS_FEATURE_STATE_FLAG) + { + printf("Enabling PUIS feature not supported on this device.\n"); + } + else + { + printf("Disabling PUIS feature not supported on this device.\n"); + } } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + if (PUIS_FEATURE_STATE_FLAG) + { + printf("Failed to enable PUIS feature!\n"); + } + else + { + printf("Failed to disable PUIS feature!\n"); + printf("If PUIS is enabled with a jumper, it cannot be disabled with this command!\n"); + printf("Remove the PUIS jumper to disable the feature in this case.\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; } } @@ -3565,13 +3898,13 @@ int32_t main(int argc, char *argv[]) if (SCSI_RESET_LP_OP) { - int resetLPResult = SUCCESS; + eReturnValues resetLPResult = SUCCESS; if (SCSI_RESET_LP_LPC > LPC_DEFAULT_CUMULATIVE_VALUES) { //requesting to reset all for (SCSI_RESET_LP_LPC = LPC_THRESHOLD_VALUES; SCSI_RESET_LP_LPC <= LPC_DEFAULT_CUMULATIVE_VALUES; ++SCSI_RESET_LP_LPC) { - int resetLPCommandRet = reset_SCSI_Log_Page(&deviceList[deviceIter], SCSI_RESET_LP_LPC, SCSI_RESET_LP_PAGE_NUMBER, SCSI_RESET_LP_SUBPAGE_NUMBER, !VOLATILE_FLAG); + eReturnValues resetLPCommandRet = reset_SCSI_Log_Page(&deviceList[deviceIter], C_CAST(eScsiLogPageControl, SCSI_RESET_LP_LPC), SCSI_RESET_LP_PAGE_NUMBER, SCSI_RESET_LP_SUBPAGE_NUMBER, !VOLATILE_FLAG); if (SUCCESS != resetLPCommandRet)//this is to catch if any LPC reset value creates an error { resetLPResult = resetLPCommandRet; @@ -3581,7 +3914,7 @@ int32_t main(int argc, char *argv[]) else { //reset just the specified information - resetLPResult = reset_SCSI_Log_Page(&deviceList[deviceIter], SCSI_RESET_LP_LPC, SCSI_RESET_LP_PAGE_NUMBER, SCSI_RESET_LP_SUBPAGE_NUMBER, !VOLATILE_FLAG); + resetLPResult = reset_SCSI_Log_Page(&deviceList[deviceIter], C_CAST(eScsiLogPageControl, SCSI_RESET_LP_LPC), SCSI_RESET_LP_PAGE_NUMBER, SCSI_RESET_LP_SUBPAGE_NUMBER, !VOLATILE_FLAG); } switch (resetLPResult) { @@ -3621,82 +3954,96 @@ int32_t main(int argc, char *argv[]) if (SCSI_SET_MP_OP) { - if (strlen(SCSI_SET_MP_FILENAME) > 0)//file was given to be used to set the MP + if (safe_strlen(SCSI_SET_MP_FILENAME) > 0)//file was given to be used to set the MP { //need to open the file that was passed, and convert it to an array. //skip all newlines, spaces, underscores, dashes, slashes, etc. We should only be finding hex bytes inside this buffer (no H's or 0x's either) - FILE *modePageFile = fopen(SCSI_SET_MP_FILENAME, "r"); - if (modePageFile) + secureFileInfo* modePageFile = secure_Open_File(SCSI_SET_MP_FILENAME, "r", M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (modePageFile && modePageFile->error == SEC_FILE_SUCCESS) { //first, figure out the length of the file...this will be useful to help us allocate a big enough buffer for the data - size_t fileLength = C_CAST(size_t, get_File_Size(modePageFile)) + 1;//add 1 so that we have a null terminator once we read in the file. - uint8_t *modePageBuffer = C_CAST(uint8_t*, calloc_aligned(fileLength, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment));//this will allocate more than enough memory for us to read the file...it's extra and that's ok. - char *fileBuf = C_CAST(char*, calloc(fileLength, sizeof(char))); - if (modePageBuffer && fileBuf) - { - //read the file - if ((fileLength - 1) == fread(fileBuf, sizeof(char), (fileLength - 1), modePageFile))//need the -1 since we added an extra 1 space above for a null terminator otherwise this fails. - TJE - { - //parse the file - char *delimiters = " \n\r-_\\/|\t:;"; - char *token = strtok(fileBuf, delimiters);//add more to the delimiter list as needed - if (token) + if (modePageFile->fileSize > 0) + { + size_t fileLength = modePageFile->fileSize + 1;//add 1 so that we have a null terminator once we read in the file. + uint8_t *modePageBuffer = C_CAST(uint8_t*, safe_calloc_aligned(fileLength, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment));//this will allocate more than enough memory for us to read the file...it's extra and that's ok. + char *fileBuf = C_CAST(char*, safe_calloc(fileLength, sizeof(char))); + if (modePageBuffer && fileBuf) + { + //read the file + size_t modeBytesRead = 0; + if (secure_Read_File(modePageFile, fileBuf, fileLength, sizeof(char), fileLength - 1, &modeBytesRead) == SEC_FILE_SUCCESS && modeBytesRead == fileLength - 1) { - bool invalidCharacterOrMissingSeparator = false; - uint16_t modeBufferElementCount = 0; - do + //parse the file + rsize_t filebuflen = safe_strlen(fileBuf); + char *saveptr = M_NULLPTR; + const char *delimiters = " \n\r-_\\/|\t:;"; + char *token = common_String_Token(fileBuf, &filebuflen, delimiters, &saveptr);//add more to the delimiter list as needed + if (token) { - if (strlen(token) > 2) - { - invalidCharacterOrMissingSeparator = true; - break; - } - if (strpbrk(token, "ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()+={[}]\"'<>?,.`~")) + bool invalidCharacterOrMissingSeparator = false; + uint16_t modeBufferElementCount = 0; + do { - invalidCharacterOrMissingSeparator = true; - break; - } - //not an invalid character or a missing separator, so convert the string to an array value. - modePageBuffer[modeBufferElementCount] = C_CAST(uint8_t, strtoul(token, NULL, 16)); - ++modeBufferElementCount; - token = strtok(NULL, delimiters); - } while (token); - if (!invalidCharacterOrMissingSeparator) - { - //file is read, send the change - switch (scsi_Set_Mode_Page(&deviceList[deviceIter], modePageBuffer, modeBufferElementCount, !VOLATILE_FLAG)) + if (safe_strlen(token) > 2) + { + invalidCharacterOrMissingSeparator = true; + break; + } + if (strpbrk(token, "ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()+={[}]\"'<>?,.`~")) + { + invalidCharacterOrMissingSeparator = true; + break; + } + //not an invalid character or a missing separator, so convert the string to an array value. + modePageBuffer[modeBufferElementCount] = C_CAST(uint8_t, strtoul(token, M_NULLPTR, 16)); + ++modeBufferElementCount; + token = common_String_Token(M_NULLPTR, &filebuflen, delimiters, &saveptr); + } while (token); + if (!invalidCharacterOrMissingSeparator) { - case SUCCESS: - if (VERBOSITY_QUIET < toolVerbosity) + //file is read, send the change + switch (scsi_Set_Mode_Page(&deviceList[deviceIter], modePageBuffer, modeBufferElementCount, !VOLATILE_FLAG)) { - printf("Successfully set SCSI mode page!\n"); - if (deviceList[deviceIter].drive_info.numberOfLUs > 1) + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) { - printf("NOTE: This command may have affected more than 1 logical unit\n"); + printf("Successfully set SCSI mode page!\n"); + if (deviceList[deviceIter].drive_info.numberOfLUs > 1) + { + printf("NOTE: This command may have affected more than 1 logical unit\n"); + } } + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to change the requested values in the mode page. These may not be changable or are an invalid combination.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to set the mode page changes that were requested.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; } - break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Unable to change the requested values in the mode page. These may not be changable or are an invalid combination.\n"); - } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; - break; - default: + } + else + { if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to set the mode page changes that were requested.\n"); + printf("An error occurred while trying to parse the file. Please check the file format and make sure no invalid characters are provided.\n"); } exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; } } else { if (VERBOSITY_QUIET < toolVerbosity) { - printf("An error occurred while trying to parse the file. Please check the file format and make sure no invalid characters are provided.\n"); + printf("An error occurred while trying to parse the file. Please check the file format.\n"); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } @@ -3705,20 +4052,22 @@ int32_t main(int argc, char *argv[]) { if (VERBOSITY_QUIET < toolVerbosity) { - printf("An error occurred while trying to parse the file. Please check the file format.\n"); + printf("Error reading contents of mode page file!\n"); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + safe_free_aligned(&modePageBuffer); } else { if (VERBOSITY_QUIET < toolVerbosity) { - printf("Error reading contents of mode page file!\n"); + printf("Unable to allocate memory to read the file. Cannot set the mode page.\n"); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(modePageBuffer) + safe_free_aligned(&modePageBuffer); + safe_free(&fileBuf); } else { @@ -3728,9 +4077,13 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - fclose(modePageFile); - safe_Free_aligned(modePageBuffer) - safe_Free(fileBuf); + if (SEC_FILE_SUCCESS != secure_Close_File(modePageFile)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + perror("Fatal error while closing mode page file\n"); + } + } } else { @@ -3740,6 +4093,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + free_Secure_File_Info(&modePageFile); } else { @@ -3748,18 +4102,23 @@ int32_t main(int argc, char *argv[]) uint32_t rawModePageSize = 0; if (SUCCESS == get_SCSI_Mode_Page_Size(&deviceList[deviceIter], MPC_CURRENT_VALUES, SCSI_SET_MP_PAGE_NUMBER, SCSI_SET_MP_SUBPAGE_NUMBER, &rawModePageSize)) { - uint8_t *rawmodePageBuffer = C_CAST(uint8_t*, calloc(rawModePageSize, sizeof(uint8_t))); + uint8_t *rawmodePageBuffer = C_CAST(uint8_t*, safe_calloc(rawModePageSize, sizeof(uint8_t))); if (rawmodePageBuffer) { bool usedSizeByteCmd = false; - if (SUCCESS == get_SCSI_Mode_Page(&deviceList[deviceIter], MPC_CURRENT_VALUES, SCSI_SET_MP_PAGE_NUMBER, SCSI_SET_MP_SUBPAGE_NUMBER, NULL, NULL, true, rawmodePageBuffer, rawModePageSize, NULL, &usedSizeByteCmd)) + if (SUCCESS == get_SCSI_Mode_Page(&deviceList[deviceIter], MPC_CURRENT_VALUES, SCSI_SET_MP_PAGE_NUMBER, SCSI_SET_MP_SUBPAGE_NUMBER, M_NULLPTR, M_NULLPTR, true, rawmodePageBuffer, rawModePageSize, M_NULLPTR, &usedSizeByteCmd)) { uint32_t modeHeaderLen = usedSizeByteCmd ? MODE_PARAMETER_HEADER_6_LEN : MODE_PARAMETER_HEADER_10_LEN; - uint32_t blockDescriptorLength = (deviceList[deviceIter].drive_info.scsiVersion < SCSI_VERSION_SCSI2) ? SHORT_LBA_BLOCK_DESCRIPTOR_LEN : 0;//the get_SCSI_MP function will only pull a block descriptor on old drives for compatibility using mode sense 6 commands, which is why this check is minimal + uint32_t blockDescriptorLength = usedSizeByteCmd ? rawmodePageBuffer[2] : M_BytesTo2ByteValue(rawmodePageBuffer[6], rawmodePageBuffer[7]); uint32_t dataLengthAdjustment = modeHeaderLen + blockDescriptorLength; uint32_t modePageSize = rawModePageSize - dataLengthAdjustment; uint8_t* modePageBuffer = rawmodePageBuffer + dataLengthAdjustment; //TODO: some of this code can probably be simplified a bit more than it currently is. + if (blockDescriptorLength > 0) + { + //Before going too far, clear the block descriptor to zeroes to make sure we are clearly communicating that no changes are requested. + memset(&rawmodePageBuffer[modeHeaderLen], 0, blockDescriptorLength); + } //now we have the data, we can begin modifying the field requested. if (SCSI_SET_MP_FIELD_LEN_BITS % BITSPERBYTE) { @@ -3778,7 +4137,7 @@ int32_t main(int argc, char *argv[]) } //check how many full bytes worth of bits we'll be setting. uint8_t fullBytesToSet = remainingBits / BITSPERBYTE; - remainingBits -= fullBytesToSet * BITSPERBYTE; + remainingBits -= C_CAST(uint8_t, fullBytesToSet * BITSPERBYTE); lowUnalignedBits = remainingBits; //now we know how we need to set things, so lets start at the end (lsb) and work up from there. //as we set the necessary bits, we will shift the original value to the right to make it easy to set each piece of the bits. @@ -3788,11 +4147,11 @@ int32_t main(int argc, char *argv[]) { ++offset;//add one to the offset since these bits are on another byte past the starting offset and any full bytes we need to set //need to create a mask and take the lowest bits that we need and place then in this byte starting at bit 7 - uint8_t mask = M_GETBITRANGE(UINT8_MAX, 7, 7 - (lowUnalignedBits - 1)) << (7 - lowUnalignedBits + 1); + uint8_t mask = C_CAST(uint8_t, M_GETBITRANGE(UINT8_MAX, 7, 7 - (lowUnalignedBits - 1)) << (7 - lowUnalignedBits + 1)); //clear the requested bits first - modePageBuffer[offset] &= ~(mask); + modePageBuffer[offset] &= C_CAST(uint8_t, ~(mask)); //now set them as requested - modePageBuffer[offset] |= (mask & (SCSI_SET_MP_FIELD_VALUE << (7 - lowUnalignedBits + 1))); + modePageBuffer[offset] |= C_CAST(uint8_t, (mask & (SCSI_SET_MP_FIELD_VALUE << (7 - lowUnalignedBits + 1)))); //bits are set, decrease the offset for the next operation --offset; SCSI_SET_MP_FIELD_VALUE >>= lowUnalignedBits; @@ -3807,21 +4166,21 @@ int32_t main(int argc, char *argv[]) if (highUnalignedBits > 0) { //need to create a mask and take the highest bits (only ones remaining at this point) that we need and place then in this byte starting at bit 0 - uint8_t mask = M_GETBITRANGE(UINT8_MAX, (highUnalignedBits - 1), (highUnalignedBits - 1) - (highUnalignedBits - 1)) << ((highUnalignedBits - 1) - highUnalignedBits + 1); + uint8_t mask = C_CAST(uint8_t, M_GETBITRANGE(UINT8_MAX, (highUnalignedBits - 1), (highUnalignedBits - 1) - (highUnalignedBits - 1)) << ((highUnalignedBits - 1) - highUnalignedBits + 1)); //clear the requested bits first - modePageBuffer[SCSI_SET_MP_BYTE] &= ~(mask); + modePageBuffer[SCSI_SET_MP_BYTE] &= C_CAST(uint8_t, ~(mask)); //now set them as requested - modePageBuffer[SCSI_SET_MP_BYTE] |= (mask & (SCSI_SET_MP_FIELD_VALUE << ((highUnalignedBits - 1) - highUnalignedBits + 1))); + modePageBuffer[SCSI_SET_MP_BYTE] |= C_CAST(uint8_t, (mask & (SCSI_SET_MP_FIELD_VALUE << ((highUnalignedBits - 1) - highUnalignedBits + 1)))); } } else { //setting bits within a single byte. - uint8_t mask = M_GETBITRANGE(UINT8_MAX, SCSI_SET_MP_BIT, SCSI_SET_MP_BIT - (SCSI_SET_MP_FIELD_LEN_BITS - 1)) << (SCSI_SET_MP_BIT - SCSI_SET_MP_FIELD_LEN_BITS + 1); + uint8_t mask = C_CAST(uint8_t, M_GETBITRANGE(UINT8_MAX, SCSI_SET_MP_BIT, SCSI_SET_MP_BIT - (SCSI_SET_MP_FIELD_LEN_BITS - 1)) << (SCSI_SET_MP_BIT - SCSI_SET_MP_FIELD_LEN_BITS + 1)); //clear the requested bits first - modePageBuffer[SCSI_SET_MP_BYTE] &= ~(mask); + modePageBuffer[SCSI_SET_MP_BYTE] &= C_CAST(uint8_t, ~(mask)); //now set them as requested - modePageBuffer[SCSI_SET_MP_BYTE] |= (mask & (SCSI_SET_MP_FIELD_VALUE << (SCSI_SET_MP_BIT - SCSI_SET_MP_FIELD_LEN_BITS + 1))); + modePageBuffer[SCSI_SET_MP_BYTE] |= C_CAST(uint8_t, (mask & (SCSI_SET_MP_FIELD_VALUE << (SCSI_SET_MP_BIT - SCSI_SET_MP_FIELD_LEN_BITS + 1)))); } } else @@ -3831,7 +4190,7 @@ int32_t main(int argc, char *argv[]) uint8_t byteNumber = 0; while (fieldWidthBytes >= 1) { - modePageBuffer[SCSI_SET_MP_BYTE + (fieldWidthBytes - 1)] = C_CAST(uint8_t, (M_ByteN(byteNumber) & SCSI_SET_MP_FIELD_VALUE) >> (BITSPERBYTE * byteNumber)); + modePageBuffer[SCSI_SET_MP_BYTE + (fieldWidthBytes - 1)] = C_CAST(uint8_t, (C_CAST(uint64_t, M_ByteN(byteNumber)) & SCSI_SET_MP_FIELD_VALUE) >> (BITSPERBYTE * byteNumber)); --fieldWidthBytes; ++byteNumber; } @@ -3873,7 +4232,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; } - safe_Free(rawmodePageBuffer); + safe_free(&rawmodePageBuffer); } else { @@ -3894,10 +4253,94 @@ int32_t main(int argc, char *argv[]) } } } + + if (WRV_INFO) + { + wrvInfo info; + memset(&info, 0, sizeof(wrvInfo)); + switch (get_Write_Read_Verify_Info(&deviceList[deviceIter], &info)) + { + case SUCCESS: + print_Write_Read_Verify_Info(&info); + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Write-Read-Verify feature is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to get Write-Read-Verify feature infomation.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + if (WRV_FLAG) + { + if (WRV_DISABLE) + { + switch (disable_Write_Read_Verify(&deviceList[deviceIter])) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Successfully disabled Write-Read-Verify feature\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Write-Read-Verify feature is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to disable Write-Read-Verify feature.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + else + { + switch (set_Write_Read_Verify(&deviceList[deviceIter], WRV_ALL, WRV_VENDOR, WRV_USER_VALUE)) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Successfully enabled Write-Read-Verify feature\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Write-Read-Verify feature is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to enable Write-Read-Verify feature.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + } //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -3954,6 +4397,8 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s 08:2:2:1=0\n", util_name, deviceHandleExample, SCSI_SET_MP_LONG_OPT_STRING); printf("\t%s -d %s --%s file=modePageToChange.txt\n", util_name, deviceHandleExample, SCSI_SET_MP_LONG_OPT_STRING); printf("\t%s -d %s --%s 134217728\n", util_name, deviceHandleExample, PROVISION_LONG_OPT_STRING); + printf("\t%s -d %s --%s 134217728 --%s\n", util_name, deviceHandleExample, SET_MAX_LBA_LONG_OPT_STRING, CHANGE_ID_STRING_LONG_OPT_STRING); + printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, CAPACITY_MODEL_NUMBER_MAPPING_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, ATA_DCO_IDENTIFY_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, ATA_DCO_RESTORE_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, ATA_DCO_FREEZE_LONG_OPT_STRING); @@ -3961,7 +4406,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -4001,6 +4446,8 @@ void utility_Usage(bool shortUsage) print_Test_Unit_Ready_Help(shortUsage); print_Fast_Discovery_Help(shortUsage); //utility tests/operations go here - alphabetized + print_Capacity_Model_Number_Mapping_Help(shortUsage); + print_Change_Id_String_Help(shortUsage); print_Phy_Speed_Help(shortUsage); print_Read_Look_Ahead_Help(shortUsage); print_Restore_Max_LBA_Help(shortUsage); @@ -4023,6 +4470,7 @@ void utility_Usage(bool shortUsage) print_SCT_Write_Cache_Help(shortUsage); print_SCT_Write_Cache_Reordering_Help(shortUsage); print_SCT_Error_Recovery_Write_Help(shortUsage); + print_WRV_Help(shortUsage); //SAS Only Options printf("\n\tSAS Only:\n\t========\n"); diff --git a/utils/C/openSeaChest/openSeaChest_Defect.c b/utils/C/openSeaChest/openSeaChest_Defect.c new file mode 100644 index 00000000..1fc242d9 --- /dev/null +++ b/utils/C/openSeaChest/openSeaChest_Defect.c @@ -0,0 +1,1656 @@ +// +// Do NOT modify or remove this copyright and license +// +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// +// This software is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// ****************************************************************************************** +// +// \file openSeaChest_Defect.c CLI to create, view, and manage defects + +////////////////////// +// Included files // +////////////////////// +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" + +#include "getopt.h" +#include "EULA.h" +#include "openseachest_util_options.h" +#include "operations.h" +#include "drive_info.h" +#include "dst.h" +#include "smart.h" +#include "seagate_operations.h" +#include "defect.h" + +//////////////////////// +// Global Variables // +//////////////////////// +const char* util_name = "openSeaChest_Defect"; +const char* buildVersion = "0.9.0"; + +//////////////////////////// +// functions to declare // +//////////////////////////// +static void utility_Usage(bool shortUsage); +//----------------------------------------------------------------------------- +// +// main() +// +//! \brief Description: main function that runs and decides what to do based on the passed in args +// +// Entry: +//! \param argc = +//! \param argv = +//! +// Exit: +//! \return exitCode = error code returned by the application +// +//----------------------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + ///////////////// + // Variables // + ///////////////// + //common utility variables + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; + DEVICE_UTIL_VARS + DEVICE_INFO_VAR + SAT_INFO_VAR + //DATA_ERASE_VAR + LICENSE_VAR + ECHO_COMMAND_LINE_VAR + SCAN_FLAG_VAR + NO_BANNER_VAR + AGRESSIVE_SCAN_FLAG_VAR + SHOW_BANNER_VAR + SHOW_HELP_VAR + TEST_UNIT_READY_VAR + FAST_DISCOVERY_VAR + MODEL_MATCH_VARS + FW_MATCH_VARS + CHILD_MODEL_MATCH_VARS + CHILD_FW_MATCH_VARS + ONLY_SEAGATE_VAR + FORCE_DRIVE_TYPE_VARS + SINGLE_SECTOR_DATA_ERASE_VAR + ENABLE_LEGACY_PASSTHROUGH_VAR + //scan output flags + SCAN_FLAGS_UTIL_VARS + DST_AND_CLEAN_VAR + ERROR_LIMIT_VAR +#if defined (ENABLE_CSMI) + CSMI_FORCE_VARS + CSMI_VERBOSE_VAR +#endif + + CHECK_PENDING_LIST_COUNT_VARS + CHECK_GROWN_LIST_COUNT_VARS + SHOW_PENDING_LIST_VAR + CREATE_UNCORRECTABLE_VAR + CREATE_UNCORRECTABLE_LBA_VAR + UNCORRECTABLE_RANGE_VAR + RANDOM_UNCORRECTABLES_VAR + READ_UNCORRECTABLES_VAR + FLAG_UNCORRECTABLES_VAR + CORRUPT_LBA_VAR + CORRUPT_LBA_RANGE_VAR + CORRUPT_RANDOM_LBAS_VAR + BYTES_TO_CORRUPT_VAR + SCSI_DEFECTS_VARS + + int args = 0; + int argIndex = 0; + int optionIndex = 0; + + struct option longopts[] = { + //common command line options + DEVICE_LONG_OPT, + HELP_LONG_OPT, + DEVICE_INFO_LONG_OPT, + SAT_INFO_LONG_OPT, + USB_CHILD_INFO_LONG_OPT, + SCAN_LONG_OPT, + NO_BANNER_OPT, + AGRESSIVE_SCAN_LONG_OPT, + SCAN_FLAGS_LONG_OPT, + VERSION_LONG_OPT, + VERBOSE_LONG_OPT, + QUIET_LONG_OPT, + LICENSE_LONG_OPT, + ECHO_COMMAND_LIN_LONG_OPT, + TEST_UNIT_READY_LONG_OPT, + FAST_DISCOVERY_LONG_OPT, + ONLY_SEAGATE_LONG_OPT, + MODEL_MATCH_LONG_OPT, + FW_MATCH_LONG_OPT, + CHILD_MODEL_MATCH_LONG_OPT, + CHILD_FW_MATCH_LONG_OPT, + FORCE_DRIVE_TYPE_LONG_OPTS, + ENABLE_LEGACY_PASSTHROUGH_LONG_OPT, + CONFIRM_LONG_OPT, +#if defined (ENABLE_CSMI) + CSMI_VERBOSE_LONG_OPT, + CSMI_FORCE_LONG_OPTS, +#endif + //tool specific options go here + ERROR_LIMIT_LONG_OPT, + DST_AND_CLEAN_LONG_OPT, + CHECK_PENDING_LIST_COUNT_LONG_OPT, + CHECK_GROWN_LIST_COUNT_LONG_OPT, + SHOW_PENDING_LIST_LONG_OPT, + CREATE_UNCORRECTABLE_LONG_OPT, + UNCORRECTABLE_RANGE_LONG_OPT, + RANDOM_UNCORRECTABLES_LONG_OPT, + DISABLE_READ_UNCORRECTABLES_LONG_OPT, + FLAG_UNCORRECTABLE_LONG_OPT, + CORRUPT_LBA_LONG_OPT, + CORRUPT_LBA_RANGE_LONG_OPT, + CORRUPT_RANDOM_LBAS_LONG_OPT, + BYTES_TO_CORRUPT_LONG_OPT, + SCSI_DEFECTS_LONG_OPTS, + LONG_OPT_TERMINATOR + }; + + eVerbosityLevels toolVerbosity = VERBOSITY_DEFAULT; + +#if defined (UEFI_C_SOURCE) + //NOTE: This is a BSD function used to ensure the program name is set correctly for warning or error functions. + // This is not necessary on most modern systems other than UEFI. + // This is not used in linux so that we don't depend on libbsd + // Update the above #define check if we port to another OS that needs this to be done. + setprogname(util_name); +#endif + + //////////////////////// + // Argument Parsing // + //////////////////////// + if (argc < 2) + { + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + utility_Usage(true); + printf("\n"); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + //get options we know we need + while (1) //changed to while 1 in order to parse multiple options when longs options are involved + { + args = getopt_long(argc, argv, "d:hisSF:Vv:q%:", longopts, &optionIndex); + if (args == -1) + { + break; + } + //printf("Parsing arg <%u>\n", args); + switch (args) + { + case 0: + //parse long options that have no short option and required arguments here + if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) + { + if (strcmp(optarg, SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING) == 0) + { + SINGLE_SECTOR_DATA_ERASE_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(CONFIRM_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, ERROR_LIMIT_LONG_OPT_STRING) == 0) + { + char* unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint16(optarg, &unit, ALLOW_UNIT_SECTOR_TYPE, &ERROR_LIMIT_FLAG)) + { + if (unit) + { + if (strcmp(unit, "l") == 0) + { + ERROR_LIMIT_LOGICAL_COUNT = true; + } + else if (strcmp(unit, "p") == 0 || strcmp(unit, "") == 0) + { + ERROR_LIMIT_LOGICAL_COUNT = false; + } + else + { + print_Error_In_Cmd_Line_Args(ERROR_LIMIT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + } + else + { + print_Error_In_Cmd_Line_Args(ERROR_LIMIT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, CHECK_PENDING_LIST_COUNT_LONG_OPT_STRING) == 0) + { + //see if they want physical or logical sectors + char* unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_SECTOR_TYPE, &CHECK_PENDING_LIST_COUNT_VALUE)) + { + CHECK_PENDING_LIST_COUNT_FLAG = true; + if (unit) + { + if (strcmp(unit, "l") == 0) + { + CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG = true; + } + else if (strcmp(unit, "p") == 0 || strcmp(unit, "") == 0) + { + CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG = false; + } + else + { + print_Error_In_Cmd_Line_Args(CHECK_PENDING_LIST_COUNT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + } + else + { + print_Error_In_Cmd_Line_Args(CHECK_PENDING_LIST_COUNT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, CHECK_GROWN_LIST_COUNT_LONG_OPT_STRING) == 0) + { + char* unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_SECTOR_TYPE, &CHECK_GROWN_LIST_COUNT_VALUE)) + { + CHECK_GROWN_LIST_COUNT_FLAG = true; + if (unit) + { + if (strcmp(unit, "l") == 0) + { + CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG = true; + } + else if (strcmp(unit, "p") == 0 || strcmp(unit, "") == 0) + { + CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG = false; + } + else + { + print_Error_In_Cmd_Line_Args(CHECK_GROWN_LIST_COUNT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + } + else + { + print_Error_In_Cmd_Line_Args(CHECK_GROWN_LIST_COUNT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, SCSI_DEFECTS_LONG_OPT_STRING) == 0) + { + size_t counter = 0; + SCSI_DEFECTS_FLAG = true; + while (counter < safe_strlen(optarg)) + { + if (optarg[counter] == 'p' || optarg[counter] == 'P') + { + SCSI_DEFECTS_PRIMARY_LIST = true; + } + else if (optarg[counter] == 'g' || optarg[counter] == 'G') + { + SCSI_DEFECTS_GROWN_LIST = true; + } + ++counter; + } + if (!SCSI_DEFECTS_PRIMARY_LIST && !SCSI_DEFECTS_GROWN_LIST) + { + printf("\n Error in option --%s. You must specify showing primary (p) or grown (g) defects or both\n", SCSI_DEFECTS_LONG_OPT_STRING); + printf("Use -h option to view command line help\n"); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_I(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_DEFECTS_DESCRIPTOR_MODE)) + { + if (strcmp("shortBlock", optarg) == 0) + { + SCSI_DEFECTS_DESCRIPTOR_MODE = 0; + } + else if (strcmp("longBlock", optarg) == 0) + { + SCSI_DEFECTS_DESCRIPTOR_MODE = 3; + } + else if (strcmp("xbfi", optarg) == 0) + { + SCSI_DEFECTS_DESCRIPTOR_MODE = 1; + } + else if (strcmp("xchs", optarg) == 0) + { + SCSI_DEFECTS_DESCRIPTOR_MODE = 2; + } + else if (strcmp("bfi", optarg) == 0) + { + SCSI_DEFECTS_DESCRIPTOR_MODE = 4; + } + else if (strcmp("chs", optarg) == 0) + { + SCSI_DEFECTS_DESCRIPTOR_MODE = 5; + } + else + { + print_Error_In_Cmd_Line_Args(SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + } + else if (strcmp(longopts[optionIndex].name, CREATE_UNCORRECTABLE_LONG_OPT_STRING) == 0) + { + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &CREATE_UNCORRECTABLE_LBA_FLAG)) + { + CREATE_UNCORRECTABLE_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(CREATE_UNCORRECTABLE_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, UNCORRECTABLE_RANGE_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &UNCORRECTABLE_RANGE_FLAG)) + { + print_Error_In_Cmd_Line_Args(UNCORRECTABLE_RANGE_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RANDOM_UNCORRECTABLES_LONG_OPT_STRING) == 0) + { + if (get_And_Validate_Integer_Input_Uint16(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &RANDOM_UNCORRECTABLES_FLAG)) + { + print_Error_In_Cmd_Line_Args(RANDOM_UNCORRECTABLES_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, DISABLE_READ_UNCORRECTABLES_LONG_OPT_STRING) == 0) + { + READ_UNCORRECTABLES_FLAG = false; + } + else if (strcmp(longopts[optionIndex].name, CORRUPT_LBA_LONG_OPT_STRING) == 0) + { + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &CORRUPT_LBA_LBA)) + { + CORRUPT_LBA_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(CORRUPT_LBA_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, CORRUPT_LBA_RANGE_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &CORRUPT_LBA_RANGE_FLAG)) + { + print_Error_In_Cmd_Line_Args(CORRUPT_LBA_RANGE_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, CORRUPT_RANDOM_LBAS_LONG_OPT_STRING) == 0) + { + if (get_And_Validate_Integer_Input_Uint16(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &CORRUPT_RANDOM_LBAS_COUNT)) + { + CORRUPT_RANDOM_LBAS = true; + } + else + { + print_Error_In_Cmd_Line_Args(CORRUPT_RANDOM_LBAS_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, BYTES_TO_CORRUPT_LONG_OPT_STRING) == 0) + { + if (get_And_Validate_Integer_Input_Uint16(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &BYTES_TO_CORRUPT_VAL)) + { + BYTES_TO_CORRUPT_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(BYTES_TO_CORRUPT_LONG_OPT_STRING, C_CAST(const char*, optarg)); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) + { + MODEL_MATCH_FLAG = true; + snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) + { + FW_MATCH_FLAG = true; + snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) + { + CHILD_MODEL_MATCH_FLAG = true; + snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) + { + CHILD_FW_MATCH_FLAG = true; + snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); + } + break; + case ':'://missing required argument + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + switch (optopt) + { + case 0: + //check long options for missing arguments + break; + case DEVICE_SHORT_OPT: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify a device handle\n"); + } + return UTIL_EXIT_INVALID_DEVICE_HANDLE; + case VERBOSE_SHORT_OPT: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify a verbosity level. 0 - 4 are the valid levels\n"); + } + break; + case SCAN_FLAGS_SHORT_OPT: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify which scan options flags you want to use.\n"); + } + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Option %c requires an argument\n", optopt); + } + utility_Usage(true); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(exitCode); + } + break; + case DEVICE_SHORT_OPT: //device + if (0 != parse_Device_Handle_Argument(optarg, &RUN_ON_ALL_DRIVES, &USER_PROVIDED_HANDLE, &DEVICE_LIST_COUNT, &HANDLE_LIST)) + { + //Free any memory allocated so far, then exit. + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(255); + } + break; + case DEVICE_INFO_SHORT_OPT: //device information + DEVICE_INFO_FLAG = true; + break; + case SCAN_SHORT_OPT: //scan + SCAN_FLAG = true; + break; + case AGRESSIVE_SCAN_SHORT_OPT: + AGRESSIVE_SCAN_FLAG = true; + break; + case VERSION_SHORT_OPT: + SHOW_BANNER_FLAG = true; + break; + case VERBOSE_SHORT_OPT: //verbose + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) + { + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + break; + case QUIET_SHORT_OPT: //quiet mode + toolVerbosity = VERBOSITY_QUIET; + break; + case SCAN_FLAGS_SHORT_OPT://scan flags + get_Scan_Flags(&SCAN_FLAGS, optarg); + break; + case '?': //unknown option + printf("%s: Unable to parse %s command line option\nPlease use --%s for more information.\n", util_name, argv[optind - 1], HELP_LONG_OPT_STRING); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + case 'h': //help + SHOW_HELP_FLAG = true; + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + utility_Usage(false); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(UTIL_EXIT_NO_ERROR); + default: + break; + } + } + + atexit(print_Final_newline); + + if (ECHO_COMMAND_LINE_FLAG) + { + int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) + for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) + { + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) + { + continue; + } + printf("%s ", argv[commandLineIter]); + } + printf("\n"); + } + + if ((VERBOSITY_QUIET < toolVerbosity) && !NO_BANNER_FLAG) + { + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + } + + if (SHOW_BANNER_FLAG) + { + utility_Full_Version_Info(util_name, buildVersion, OPENSEA_TRANSPORT_MAJOR_VERSION, OPENSEA_TRANSPORT_MINOR_VERSION, OPENSEA_TRANSPORT_PATCH_VERSION, OPENSEA_COMMON_VERSION, OPENSEA_OPERATION_VERSION); + } + + if (LICENSE_FLAG) + { + print_EULA_To_Screen(); + } + + if (SCAN_FLAG || AGRESSIVE_SCAN_FLAG) + { + if (!is_Running_Elevated()) + { + print_Elevated_Privileges_Text(); + } + unsigned int scanControl = DEFAULT_SCAN; + if (AGRESSIVE_SCAN_FLAG) + { + scanControl |= AGRESSIVE_SCAN; + } +#if defined (__linux__) + if (SCAN_FLAGS.scanSD) + { + scanControl |= SD_HANDLES; + } + if (SCAN_FLAGS.scanSDandSG) + { + scanControl |= SG_TO_SD; + } +#endif + //set the drive types to show (if none are set, the lower level code assumes we need to show everything) + if (SCAN_FLAGS.scanATA) + { + scanControl |= ATA_DRIVES; + } + if (SCAN_FLAGS.scanUSB) + { + scanControl |= USB_DRIVES; + } + if (SCAN_FLAGS.scanSCSI) + { + scanControl |= SCSI_DRIVES; + } + if (SCAN_FLAGS.scanNVMe) + { + scanControl |= NVME_DRIVES; + } + if (SCAN_FLAGS.scanRAID) + { + scanControl |= RAID_DRIVES; + } + //set the interface types to show (if none are set, the lower level code assumes we need to show everything) + if (SCAN_FLAGS.scanInterfaceATA) + { + scanControl |= IDE_INTERFACE_DRIVES; + } + if (SCAN_FLAGS.scanInterfaceUSB) + { + scanControl |= USB_INTERFACE_DRIVES; + } + if (SCAN_FLAGS.scanInterfaceSCSI) + { + scanControl |= SCSI_INTERFACE_DRIVES; + } + if (SCAN_FLAGS.scanInterfaceNVMe) + { + scanControl |= NVME_INTERFACE_DRIVES; + } +#if defined (ENABLE_CSMI) + if (SCAN_FLAGS.scanIgnoreCSMI) + { + scanControl |= IGNORE_CSMI; + } + if (SCAN_FLAGS.scanAllowDuplicateDevices) + { + scanControl |= ALLOW_DUPLICATE_DEVICE; + } +#endif + if (ONLY_SEAGATE_FLAG) + { + scanControl |= SCAN_SEAGATE_ONLY; + } + scan_And_Print_Devs(scanControl, toolVerbosity); + } + // Add to this if list anything that is suppose to be independent. + // e.g. you can't say enumerate & then pull logs in the same command line. + // SIMPLE IS BEAUTIFUL + if (SCAN_FLAG || AGRESSIVE_SCAN_FLAG || SHOW_BANNER_FLAG || LICENSE_FLAG || SHOW_HELP_FLAG) + { + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_NO_ERROR); + } + + //print out errors for unknown arguments for remaining args that haven't been processed yet + for (argIndex = optind; argIndex < argc; argIndex++) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Invalid argument: %s\n", argv[argIndex]); + } + } + + if (!is_Running_Elevated()) + { + print_Elevated_Privileges_Text(); + } + + if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) + { + uint64_t flags = 0; + if (SUCCESS != get_Device_Count(&DEVICE_LIST_COUNT, flags)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to get number of devices\n"); + } + if (!is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + } + else if (DEVICE_LIST_COUNT == 0) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify one or more target devices with the --%s option to run this command.\n", DEVICE_LONG_OPT_STRING); + utility_Usage(true); + printf("Use -h option for detailed description\n\n"); + } + exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); + } + + if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) + || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) + || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) + || (FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) + || (FORCE_SCSI_FLAG && (FORCE_ATA_PIO_FLAG || FORCE_ATA_DMA_FLAG || FORCE_ATA_UDMA_FLAG))//We may need to remove this. At least when software SAT gets used. (currently only Windows ATA passthrough and FreeBSD ATA passthrough) + ) + { + printf("\nError: Only one force flag can be used at a time.\n"); + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + //need to make sure this is set when we are asked for SAT Info + if (SAT_INFO_FLAG) + { + DEVICE_INFO_FLAG = goTrue; + } + //check that we were given at least one test to perform...if not, show the help and exit + if (!(DEVICE_INFO_FLAG + || TEST_UNIT_READY_FLAG + //check for other tool specific options here + || DST_AND_CLEAN_FLAG + || CHECK_PENDING_LIST_COUNT_FLAG + || CHECK_GROWN_LIST_COUNT_FLAG + || SHOW_PENDING_LIST + || CREATE_UNCORRECTABLE_FLAG + || UNCORRECTABLE_RANGE_FLAG > 1 + || RANDOM_UNCORRECTABLES_FLAG + || CORRUPT_LBA_FLAG + || CORRUPT_RANDOM_LBAS + || SCSI_DEFECTS_FLAG + )) + { + utility_Usage(true); + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + + uint64_t flags = 0; + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + if (!DEVICE_LIST) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to allocate memory\n"); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_OPERATION_FAILURE); + } + versionBlock version; + memset(&version, 0, sizeof(versionBlock)); + version.version = DEVICE_BLOCK_VERSION; + version.size = sizeof(tDevice); + + if (TEST_UNIT_READY_FLAG) + { + flags = DO_NOT_WAKE_DRIVE; + } + + if (FAST_DISCOVERY_FLAG) + { + flags = FAST_SCAN; + } + + //set flags that can be passed down in get device regarding forcing specific ATA modes. + if (FORCE_ATA_PIO_FLAG) + { + flags |= FORCE_ATA_PIO_ONLY; + } + + if (FORCE_ATA_DMA_FLAG) + { + flags |= FORCE_ATA_DMA_SAT_MODE; + } + + if (FORCE_ATA_UDMA_FLAG) + { + flags |= FORCE_ATA_UDMA_SAT_MODE; + } + + if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) + { + + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) + { + DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; + } + ret = get_Device_List(DEVICE_LIST, DEVICE_LIST_COUNT * sizeof(tDevice), version, flags); + if (SUCCESS != ret) + { + if (ret == WARN_NOT_ALL_DEVICES_ENUMERATED) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("WARN: Not all devices enumerated correctly\n"); + } + } + else if (ret == PERMISSION_DENIED) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("WARN: Not all devices were opened. Some failed for lack of permissions\n"); + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to get device list\n"); + } + if (!is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + } + } + else + { + /*need to go through the handle list and attempt to open each handle.*/ + for (uint32_t handleIter = 0; handleIter < DEVICE_LIST_COUNT; ++handleIter) + { + /*Initializing is necessary*/ + deviceList[handleIter].sanity.size = sizeof(tDevice); + deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; +#if defined (UEFI_C_SOURCE) + deviceList[handleIter].os_info.fd = M_NULLPTR; +#elif !defined(_WIN32) + deviceList[handleIter].os_info.fd = -1; +#if defined(VMK_CROSS_COMP) + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; +#endif +#else + deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; +#endif + deviceList[handleIter].dFlags = flags; + + deviceList[handleIter].deviceVerbosity = toolVerbosity; + + if (ENABLE_LEGACY_PASSTHROUGH_FLAG) + { + deviceList[handleIter].drive_info.ata_Options.enableLegacyPassthroughDetectionThroughTrialAndError = true; + } + + /*get the device for the specified handle*/ +#if defined(_DEBUG) + printf("Attempting to open handle \"%s\"\n", HANDLE_LIST[handleIter]); +#endif + ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); +#if !defined(_WIN32) +#if !defined(VMK_CROSS_COMP) + if ((deviceList[handleIter].os_info.fd < 0) || +#else + if (((deviceList[handleIter].os_info.fd < 0) && + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || +#endif + (ret == FAILURE || ret == PERMISSION_DENIED)) +#else + if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) +#endif + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + } + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + for (uint32_t deviceIter = 0; deviceIter < DEVICE_LIST_COUNT; ++deviceIter) + { + deviceList[deviceIter].deviceVerbosity = toolVerbosity; + if (ONLY_SEAGATE_FLAG) + { + if (is_Seagate_Family(&deviceList[deviceIter]) == NON_SEAGATE) + { + /*if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive (%s) is not a Seagate drive.\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification); + }*/ + continue; + } + } + + //check for model number match + if (MODEL_MATCH_FLAG) + { + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive (%s) does not match the input model number: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG); + } + continue; + } + } + //check for fw match + if (FW_MATCH_FLAG) + { + if (strcmp(FW_STRING_FLAG, deviceList[deviceIter].drive_info.product_revision)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive's firmware (%s) does not match the input firmware revision: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_revision, FW_STRING_FLAG); + } + continue; + } + } + + //check for child model number match + if (CHILD_MODEL_MATCH_FLAG) + { + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive (%s) does not match the input child model number: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG); + } + continue; + } + } + //check for child fw match + if (CHILD_FW_MATCH_FLAG) + { + if (strcmp(CHILD_FW_STRING_FLAG, deviceList[deviceIter].drive_info.bridge_info.childDriveFW)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive's firmware (%s) does not match the input child firmware revision: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.bridge_info.childDriveFW, CHILD_FW_STRING_FLAG); + } + continue; + } + } + if (FORCE_SCSI_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing SCSI Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = SCSI_DRIVE; + } + + if (FORCE_ATA_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing ATA Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; + } + + if (FORCE_ATA_PIO_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tAttempting to force ATA Drive commands in PIO Mode\n"); + } + deviceList[deviceIter].drive_info.ata_Options.dmaSupported = false; + deviceList[deviceIter].drive_info.ata_Options.dmaMode = ATA_DMA_MODE_NO_DMA; + deviceList[deviceIter].drive_info.ata_Options.downloadMicrocodeDMASupported = false; + deviceList[deviceIter].drive_info.ata_Options.readBufferDMASupported = false; + deviceList[deviceIter].drive_info.ata_Options.readLogWriteLogDMASupported = false; + deviceList[deviceIter].drive_info.ata_Options.writeBufferDMASupported = false; + } + + if (FORCE_ATA_DMA_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tAttempting to force ATA Drive commands in DMA Mode\n"); + } + deviceList[deviceIter].drive_info.ata_Options.dmaMode = ATA_DMA_MODE_DMA; + } + + if (FORCE_ATA_UDMA_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tAttempting to force ATA Drive commands in UDMA Mode\n"); + } + deviceList[deviceIter].drive_info.ata_Options.dmaMode = ATA_DMA_MODE_UDMA; + } + + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n%s - %s - %s - %s - %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification, deviceList[deviceIter].drive_info.serialNumber, deviceList[deviceIter].drive_info.product_revision, print_drive_type(&deviceList[deviceIter])); + } + + //now start looking at what operations are going to be performed and kick them off + if (DEVICE_INFO_FLAG) + { + if (SUCCESS != print_Drive_Information(&deviceList[deviceIter], SAT_INFO_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to get device information\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + } + + if (TEST_UNIT_READY_FLAG) + { + show_Test_Unit_Ready_Status(&deviceList[deviceIter]); + } + + if (CHECK_PENDING_LIST_COUNT_FLAG) + { + uint32_t driveReportedPListCount = 0; + uint32_t pendingErrorLimit = CHECK_PENDING_LIST_COUNT_VALUE; + switch (get_Pending_List_Count(&deviceList[deviceIter], &driveReportedPListCount)) + { + case SUCCESS://got a valid count, so compare it to what the user wants to check + if (!CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG) + { + //convert the count to a physical block count..integer division shouldn't be a problem right now...but this may need revisiting.-TJE + driveReportedPListCount /= deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize; + } + if (driveReportedPListCount > pendingErrorLimit) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: drive has more pending errors than the provided limit!\n"); + printf("\tDrive reports %"PRIu32", limit is %"PRIu32" ", driveReportedPListCount, pendingErrorLimit); + if (CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG) + { + printf("Logical Blocks\n"); + } + else + { + printf("Physical Blocks\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Drive has fewer pending errors than the provided limit.\n"); + printf("\tDrive reports %"PRIu32", limit is %"PRIu32" ", driveReportedPListCount, pendingErrorLimit); + if (CHECK_PENDING_LIST_COUNT_LOGICAL_FLAG) + { + printf("Logical Blocks\n"); + } + else + { + printf("Physical Blocks\n"); + } + } + } + break; + case NOT_SUPPORTED://cannot get the count on this drive because it is not supported. + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Pending list count on this drive is not supported.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default://something went wrong + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to get Pending list count.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + if (CHECK_GROWN_LIST_COUNT_FLAG) + { + uint32_t driveReportedGListCount = 0; + uint32_t grownErrorLimit = CHECK_GROWN_LIST_COUNT_VALUE; + switch (get_Grown_List_Count(&deviceList[deviceIter], &driveReportedGListCount)) + { + case SUCCESS://got a valid count, so compare it to what the user wants to check + if (!CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG) + { + //convert the count to a physical block count..integer division shouldn't be a problem right now...but this may need revisiting.-TJE + driveReportedGListCount /= deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize; + } + if (driveReportedGListCount > grownErrorLimit) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: drive has more grown errors than the provided limit!\n"); + printf("\tDrive reports %"PRIu32", limit is %"PRIu32" ", driveReportedGListCount, grownErrorLimit); + if (CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG) + { + printf("Logical Blocks\n"); + } + else + { + printf("Physical Blocks\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Drive has fewer grown errors than the provided limit.\n"); + printf("\tDrive reports %"PRIu32", limit is %"PRIu32" ", driveReportedGListCount, grownErrorLimit); + if (CHECK_GROWN_LIST_COUNT_LOGICAL_FLAG) + { + printf("Logical Blocks\n"); + } + else + { + printf("Physical Blocks\n"); + } + } + } + break; + case NOT_SUPPORTED://cannot get the count on this drive because it is not supported. + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Grown list count on this drive is not supported.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default://something went wrong + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to get Grown list count.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + if (SHOW_PENDING_LIST) + { + //extern int get_LBAs_From_Pending_List(tDevice *device, ptrPendingDefect defectList, uint32_t *numberOfDefects); + uint32_t numberOfPendingLBAs = 0; + ptrPendingDefect pendingLBAs = C_CAST(ptrPendingDefect, safe_malloc(MAX_PLIST_ENTRIES * sizeof(pendingDefect))); + if (pendingLBAs) + { + switch (get_LBAs_From_Pending_List(&deviceList[deviceIter], pendingLBAs, &numberOfPendingLBAs)) + { + case SUCCESS: + show_Pending_List(pendingLBAs, numberOfPendingLBAs); + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Pending list is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to read pending list\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + safe_free_pending_defect(&pendingLBAs); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to allocate memory for pending list\n"); + } + exitCode = UTIL_EXIT_OPERATION_ABORTED; + } + } + + if (SCSI_DEFECTS_FLAG) + { + ptrSCSIDefectList defects = M_NULLPTR; + switch (get_SCSI_Defect_List(&deviceList[deviceIter], C_CAST(eSCSIAddressDescriptors, SCSI_DEFECTS_DESCRIPTOR_MODE), SCSI_DEFECTS_GROWN_LIST, SCSI_DEFECTS_PRIMARY_LIST, &defects)) + { + case SUCCESS: + print_SCSI_Defect_List(defects); + free_Defect_List(&defects); + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Reading Defects not supported on this device or unsupported defect list format was given.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to retrieve SCSI defect list from this device\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + if (DST_AND_CLEAN_FLAG) + { + if (SINGLE_SECTOR_DATA_ERASE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("DST And Clean\n"); + } + if (ERROR_LIMIT_LOGICAL_COUNT) + { + ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); + } + switch (run_DST_And_Clean(&deviceList[deviceIter], ERROR_LIMIT_FLAG, M_NULLPTR, M_NULLPTR, M_NULLPTR, M_NULLPTR)) + { + case UNKNOWN: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unknown Error occurred while trying to start DST and Clean\n"); + } + break; + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("DST and Clean completed successfully\n"); + } + break; + case IN_PROGRESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("A self test is currently in progress. Please wait for it to finish before starting DST and Clean\n"); + } + break; + case ABORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("DST And Clean was aborted!\n"); + } + exitCode = UTIL_EXIT_OPERATION_ABORTED; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("DST and Clean is not supported on this device\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("DST and Clean Failed!\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + printf("You must add the flag:\n\"%s\" \n", SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING); + printf("to the command line arguments to run a dst and clean operation.\n\n"); + printf("e.g.: %s -d %s --%s --confirm %s\n\n", util_name, deviceHandleExample, DST_AND_CLEAN_LONG_OPT_STRING, SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING); + } + } + } + + if (CREATE_UNCORRECTABLE_FLAG && CREATE_UNCORRECTABLE_LBA_FLAG != UINT64_MAX) + { + if (UNCORRECTABLE_RANGE_FLAG > 0 && UNCORRECTABLE_RANGE_FLAG < deviceList[deviceIter].drive_info.deviceMaxLba) + { + if (toolVerbosity > VERBOSITY_QUIET) + { + if (!FLAG_UNCORRECTABLES_FLAG) + { + printf("Creating uncorrectable errors at LBA %"PRIu64" for a range of %"PRIu64" LBAs\n.", CREATE_UNCORRECTABLE_LBA_FLAG, UNCORRECTABLE_RANGE_FLAG); + } + else + { + printf("Flagging uncorrectable errors at LBA %"PRIu64" for a range of %"PRIu64" LBAs\n.", CREATE_UNCORRECTABLE_LBA_FLAG, UNCORRECTABLE_RANGE_FLAG); + } + } + eReturnValues uncorrectableRet = UNKNOWN; + if (!FLAG_UNCORRECTABLES_FLAG) + { + uncorrectableRet = create_Uncorrectables(&deviceList[deviceIter], CREATE_UNCORRECTABLE_LBA_FLAG, UNCORRECTABLE_RANGE_FLAG, READ_UNCORRECTABLES_FLAG, M_NULLPTR, M_NULLPTR); + } + else + { + uncorrectableRet = flag_Uncorrectables(&deviceList[deviceIter], CREATE_UNCORRECTABLE_LBA_FLAG, UNCORRECTABLE_RANGE_FLAG, M_NULLPTR, M_NULLPTR); + } + switch (uncorrectableRet) + { + case SUCCESS: + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Successfully flagged uncorrectable errors on the device.\n"); + } + else + { + printf("Successfully created uncorrectable errors on the device.\n"); + } + } + break; + case NOT_SUPPORTED: + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Flagging uncorrectable errors is not supported by this device at this time.\n"); + } + else + { + printf("Creating uncorrectable errors is not supported by this device at this time.\n"); + } + } + break; + default: + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Failed to flag uncorrectable errors on the device.\n"); + } + else + { + printf("Failed to create uncorrectable errors on the device.\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + else + { + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("The range specified is invalid. Please enter a range that does not exceed the MaxLBA of the device from the specified starting LBA.\n"); + } + } + } + else if (CREATE_UNCORRECTABLE_FLAG) + { + if (UNCORRECTABLE_RANGE_FLAG > 1) + { + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("You must used the --createUncorrectable option with an LBA to provide a starting point for the range provided.\n"); + } + } + } + + if (RANDOM_UNCORRECTABLES_FLAG > 0) + { + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Flagging %"PRIu16" random uncorrectables on the device\n", RANDOM_UNCORRECTABLES_FLAG); + } + else + { + printf("Creating %"PRIu16" random uncorrectables on the device\n", RANDOM_UNCORRECTABLES_FLAG); + } + } + switch (create_Random_Uncorrectables(&deviceList[deviceIter], RANDOM_UNCORRECTABLES_FLAG, READ_UNCORRECTABLES_FLAG, FLAG_UNCORRECTABLES_FLAG, M_NULLPTR, M_NULLPTR)) + { + case SUCCESS: + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Successfully flagged random uncorrectable errors on the device.\n"); + } + else + { + printf("Successfully created random uncorrectable errors on the device.\n"); + } + } + break; + case NOT_SUPPORTED: + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Flagging random uncorrectable errors is not supported by this device at this time.\n"); + } + else + { + printf("Creating random uncorrectable errors is not supported by this device at this time.\n"); + } + } + break; + default: + if (toolVerbosity > VERBOSITY_QUIET) + { + if (FLAG_UNCORRECTABLES_FLAG) + { + printf("Failed to flag random uncorrectable errors on the device.\n"); + } + else + { + printf("Failed to create random uncorrectable errors on the device.\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + if (CORRUPT_LBA_FLAG) + { + if (is_Read_Long_Write_Long_Supported(&deviceList[deviceIter])) + { + bool bytesToCorruptSet = true; + if (!BYTES_TO_CORRUPT_FLAG) + { + //this means the user didn't enter anything, so we need to use a default value. + //The defaults here were defined internally and it's not clear if they are product specific or not. + if (deviceList[deviceIter].drive_info.devicePhyBlockSize >= 512 && deviceList[deviceIter].drive_info.devicePhyBlockSize <= 1024)//trying to handle drives that may be formatted to 520, etc sizes + { + BYTES_TO_CORRUPT_VAL = 62; + } + else if (deviceList[deviceIter].drive_info.devicePhyBlockSize >= 4096 && deviceList[deviceIter].drive_info.devicePhyBlockSize <= 8192) + { + BYTES_TO_CORRUPT_VAL = 360; + } + else + { + exitCode = UTIL_EXIT_OPERATION_ABORTED; + bytesToCorruptSet = false; + printf("ERROR: Unable to determine default number of bytes to corrupt. Please specify it with the --%s option.\n", BYTES_TO_CORRUPT_LONG_OPT_STRING); + } + } + if (bytesToCorruptSet) + { + //create the correctable error condition + switch (corrupt_LBAs(&deviceList[deviceIter], CORRUPT_LBA_LBA, CORRUPT_LBA_RANGE_FLAG, READ_UNCORRECTABLES_FLAG, BYTES_TO_CORRUPT_VAL, M_NULLPTR, M_NULLPTR)) + { + case SUCCESS: + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Successfully corrupted %" PRIu16" bytes on the device at LBA %" PRIu64 " to LBA %" PRIu64 ".\n", BYTES_TO_CORRUPT_VAL, CORRUPT_LBA_LBA, CORRUPT_LBA_LBA + CORRUPT_LBA_RANGE_FLAG); + } + break; + case NOT_SUPPORTED: + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Creating correctable errors is not supported by this device at this time.\n"); + } + break; + default: + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Failed to create correctable errors on the device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + } + else + { + printf("Creating correctable errors is not supported on this drive.\n"); + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } + } + + if (CORRUPT_RANDOM_LBAS && CORRUPT_RANDOM_LBAS_COUNT > 0) + { + if (is_Read_Long_Write_Long_Supported(&deviceList[deviceIter])) + { + bool bytesToCorruptSet = true; + if (!BYTES_TO_CORRUPT_FLAG) + { + //this means the user didn't enter anything, so we need to use a default value. + //The defaults here were defined internally and it's not clear if they are product specific or not. + if (deviceList[deviceIter].drive_info.devicePhyBlockSize >= 512 && deviceList[deviceIter].drive_info.devicePhyBlockSize <= 1024)//trying to handle drives that may be formatted to 520, etc sizes + { + BYTES_TO_CORRUPT_VAL = 62; + } + else if (deviceList[deviceIter].drive_info.devicePhyBlockSize >= 4096 && deviceList[deviceIter].drive_info.devicePhyBlockSize <= 8192) + { + BYTES_TO_CORRUPT_VAL = 360; + } + else + { + exitCode = UTIL_EXIT_OPERATION_ABORTED; + bytesToCorruptSet = false; + printf("ERROR: Unable to determine default number of bytes to corrupt. Please specify it with the --%s option.\n", BYTES_TO_CORRUPT_LONG_OPT_STRING); + } + } + if (bytesToCorruptSet) + { + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Corrupting %"PRIu16" random LBAs on the device\n", CORRUPT_RANDOM_LBAS_COUNT); + } + switch (corrupt_Random_LBAs(&deviceList[deviceIter], CORRUPT_RANDOM_LBAS_COUNT, READ_UNCORRECTABLES_FLAG, BYTES_TO_CORRUPT_VAL, M_NULLPTR, M_NULLPTR)) + { + case SUCCESS: + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Successfully corrupted %" PRIu16 "random LBAs on the device.\n", CORRUPT_RANDOM_LBAS_COUNT); + } + break; + case NOT_SUPPORTED: + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Corrupting random LBAs is not supported by this device at this time.\n"); + } + break; + default: + if (toolVerbosity > VERBOSITY_QUIET) + { + printf("Failed to corrupt random LBAs on the device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + } + else + { + printf("Creating correctable errors is not supported on this drive.\n"); + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } + } + + //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. + close_Device(&deviceList[deviceIter]); + } + free_device_list(&DEVICE_LIST); + exit(exitCode); +} + +//----------------------------------------------------------------------------- +// +// Utility_usage() +// +//! \brief Description: Dump the utility usage information +// +// Entry: +//! \param NONE +//! +// Exit: +//! \return VOID +// +//----------------------------------------------------------------------------- +void utility_Usage(bool shortUsage) +{ + //everything needs a help option right? + printf("Usage\n"); + printf("=====\n"); + printf("\t %s [-d %s] {arguments} {options}\n\n", util_name, deviceHandleName); + + printf("\nExamples\n"); + printf("========\n"); + //example usage + printf("\t%s --%s\n", util_name, SCAN_LONG_OPT_STRING); + printf("\t%s -d %s -%c\n", util_name, deviceHandleExample, DEVICE_INFO_SHORT_OPT); + //return codes + printf("\nReturn codes\n"); + printf("============\n"); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); + + //utility options - alphabetized + printf("\nUtility Options\n"); + printf("===============\n"); +#if defined (ENABLE_CSMI) + print_CSMI_Force_Flags_Help(shortUsage); + print_CSMI_Verbose_Help(shortUsage); +#endif + print_Echo_Command_Line_Help(shortUsage); + print_Enable_Legacy_USB_Passthrough_Help(shortUsage); + print_Force_ATA_Help(shortUsage); + print_Force_ATA_DMA_Help(shortUsage); + print_Force_ATA_PIO_Help(shortUsage); + print_Force_ATA_UDMA_Help(shortUsage); + print_Force_SCSI_Help(shortUsage); + print_Help_Help(shortUsage); + print_License_Help(shortUsage); + print_Model_Match_Help(shortUsage); + print_No_Banner_Help(shortUsage); + print_Firmware_Revision_Match_Help(shortUsage); + print_Only_Seagate_Help(shortUsage); + print_Quiet_Help(shortUsage, util_name); + print_Verbose_Help(shortUsage); + print_Version_Help(shortUsage, util_name); + + //the test options + printf("\nUtility Arguments\n"); + printf("=================\n"); + //Common (across utilities) - alphabetized + print_Device_Help(shortUsage, deviceHandleExample); + print_Scan_Flags_Help(shortUsage); + print_Device_Information_Help(shortUsage); + print_Scan_Help(shortUsage, deviceHandleExample); + print_Agressive_Scan_Help(shortUsage); + print_SAT_Info_Help(shortUsage); + print_Test_Unit_Ready_Help(shortUsage); + print_Fast_Discovery_Help(shortUsage); + //utility tests/operations go here - alphabetized + print_Error_Limit_Help(shortUsage); + //multiple interfaces + print_Check_Grown_List_Help(shortUsage); + print_Check_Pending_List_Help(shortUsage); + print_Show_Pending_List_Help(shortUsage); + + //SATA Only Options + //printf("\n\tSATA Only:\n\n"); + + //SAS Only Options + printf("\n\tSAS Only:\n\n"); + print_SCSI_Defects_Format_Help(shortUsage); + print_SCSI_Defects_Help(shortUsage); + + + //data destructive commands - alphabetized + printf("Data Destructive Commands (Seagate only)\n"); + printf("========================================\n"); + //utility data destructive tests/operations go here + print_Bytes_To_Corrupt_Help(shortUsage); + print_DST_And_Clean_Help(shortUsage); + print_Corrupt_LBA_Help(shortUsage); + print_Corrupt_Random_LBAs_Help(shortUsage); + print_Corrupt_Range_Help(shortUsage); + print_Disable_Read_Uncorrectables_Help(shortUsage); + print_Flag_Uncorrectable_Help(shortUsage); + print_Create_Uncorrectable_Help(shortUsage); + print_Random_Uncorrectable_Help(shortUsage); + print_Uncorrectable_Range_Help(shortUsage); +} diff --git a/utils/C/openSeaChest/openSeaChest_Erase.c b/utils/C/openSeaChest/openSeaChest_Erase.c index 15ca0c99..89d28c3b 100644 --- a/utils/C/openSeaChest/openSeaChest_Erase.c +++ b/utils/C/openSeaChest/openSeaChest_Erase.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,18 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include "common_platform.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "secure_file.h" +#include "pattern_utils.h" +#include "math_utils.h" +#include "sleep.h" +#if defined (_WIN32) +#include "windows_version_detect.h" //for WinPE check #endif #include "getopt.h" #include "EULA.h" @@ -27,12 +35,12 @@ #include "cmds.h" #if !defined(DISABLE_TCG_SUPPORT) #include "common_TCG.h" +#include "operations.h" #include "revertSP.h" #include "revert.h" #include "genkey.h" #include "port_locking.h" #endif -#include "operations.h" #include "host_erase.h" #include "ata_Security.h" #include "sanitize.h" @@ -47,7 +55,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Erase"; -const char *buildVersion = "4.3.6"; +const char *buildVersion = "4.6.0"; typedef enum _eSeaChestEraseExitCodes { @@ -73,14 +81,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -127,7 +135,14 @@ int32_t main(int argc, char *argv[]) ATA_SECURITY_ERASE_OP_VARS ATA_SECURITY_FORCE_SAT_VARS //sanitize + SANITIZE_FREEZE_VAR + SANITIZE_ANTIFREEZE_VAR SANITIZE_UTIL_VARS + SANITIZE_AUSE_VAR + SANITIZE_IPBP_VAR + SANITIZE_OVERWRITE_PASSES_VAR + ZONE_NO_RESET_VAR + NO_DEALLOCATE_AFTER_ERASE_VAR //NVMe Sanitize option only at this time. //write same WRITE_SAME_UTIL_VARS //tcgGenkey @@ -152,8 +167,9 @@ int32_t main(int argc, char *argv[]) HIDE_LBA_COUNTER_VAR LOWLEVEL_INFO_VAR ERASE_RESTORE_MAX_VAR + REFRESH_FILE_SYSTEMS_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -204,7 +220,14 @@ int32_t main(int argc, char *argv[]) TCG_SID_LONG_OPT, TCG_PSID_LONG_OPT, #endif - { "sanitize", required_argument, NULL, 'e' }, //has a purposely unadvertized short option + SANITIZE_FREEZE_LONG_OPT, + SANITIZE_ANTIFREEZE_LONG_OPT, + SANITIZE_LONG_OPT, + SANITIZE_AUSE_LONG_OPT, + SANITIZE_IPBP_LONG_OPT, + SANITIZE_OVERWRITE_PASSES_LONG_OPT, + ZONE_NO_RESET_LONG_OPT, + NO_DEALLOCATE_AFTER_ERASE_LONG_OPT, WRITE_SAME_LONG_OPTS, SHOW_ERASE_SUPPORT_LONG_OPT, PERFORM_FASTEST_ERASE_LONG_OPT, @@ -222,6 +245,7 @@ int32_t main(int argc, char *argv[]) NVM_FORMAT_OPTIONS_LONG_OPTS, ZERO_VERIFY_LONG_OPT, ERASE_RESTORE_MAX_PREP_LONG_OPT, + REFRESH_FILE_SYSTEMS_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -280,7 +304,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TRIM_RANGE_LONG_OPT_STRING) == 0 || strcmp(longopts[optionIndex].name, UNMAP_RANGE_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &TRIM_UNMAP_RANGE_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &TRIM_UNMAP_RANGE_FLAG)) { if (strcmp(longopts[optionIndex].name, TRIM_RANGE_LONG_OPT_STRING) == 0) { @@ -295,7 +319,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TRIM_LONG_OPT_STRING) == 0 || strcmp(longopts[optionIndex].name, UNMAP_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &TRIM_UNMAP_START_FLAG)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &TRIM_UNMAP_START_FLAG)) { RUN_TRIM_UNMAP_FLAG = true; } @@ -327,7 +351,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, OVERWRITE_RANGE_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &OVERWRITE_RANGE_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &OVERWRITE_RANGE_FLAG)) { print_Error_In_Cmd_Line_Args(OVERWRITE_RANGE_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -335,7 +359,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, OVERWRITE_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &OVERWRITE_START_FLAG)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &OVERWRITE_START_FLAG)) { RUN_OVERWRITE_FLAG = true; } @@ -360,19 +384,31 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, HOURS_TIME_LONG_OPT_STRING) == 0) { - HOURS_TIME_FLAG = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &HOURS_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(HOURS_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, MINUTES_TIME_LONG_OPT_STRING) == 0) { - MINUTES_TIME_FLAG = C_CAST(uint16_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &MINUTES_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(MINUTES_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, SECONDS_TIME_LONG_OPT_STRING) == 0) { - SECONDS_TIME_FLAG = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SECONDS_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(SECONDS_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, WRITE_SAME_RANGE_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &WRITE_SAME_RANGE_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &WRITE_SAME_RANGE_FLAG)) { print_Error_In_Cmd_Line_Args(WRITE_SAME_RANGE_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -380,7 +416,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, WRITE_SAME_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &WRITE_SAME_START_FLAG)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &WRITE_SAME_START_FLAG)) { RUN_WRITE_SAME_FLAG = true; } @@ -418,13 +454,7 @@ int32_t main(int argc, char *argv[]) FORMAT_UNIT_FLAG = true; if (strcmp(optarg, "current") != 0) { - uint64_t tempSectorSize = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &tempSectorSize)) - { - //set the sector size - FORMAT_SECTOR_SIZE = C_CAST(uint16_t, tempSectorSize); - } - else + if (!get_And_Validate_Integer_Input_Uint16(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &FORMAT_SECTOR_SIZE)) { print_Error_In_Cmd_Line_Args(FORMAT_UNIT_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -436,12 +466,7 @@ int32_t main(int argc, char *argv[]) NVM_FORMAT_FLAG = true; if (strcmp(optarg, "current") != 0) { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &temp)) - { - NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM = C_CAST(uint32_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Uint32(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM)) { print_Error_In_Cmd_Line_Args(NVM_FORMAT_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -486,7 +511,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_PI_TYPE_LONG_OPT_STRING) == 0) { - NVM_FORMAT_PI_TYPE = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_PI_TYPE) || NVM_FORMAT_PI_TYPE > 3) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_PI_TYPE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_PI_LOCATION_LONG_OPT_STRING) == 0) { @@ -506,7 +535,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING) == 0) { - NVM_FORMAT_METADATA_SIZE = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_METADATA_SIZE)) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_METADATA_SETTING_LONG_OPT_STRING) == 0) { @@ -526,7 +559,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, DISPLAY_LBA_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &DISPLAY_LBA_THE_LBA)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &DISPLAY_LBA_THE_LBA)) { DISPLAY_LBA_FLAG = true; } @@ -551,9 +584,13 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, FAST_FORMAT_LONG_OPT_STRING) == 0) { - FAST_FORMAT_FLAG = C_CAST(eFormatType, atoi(optarg)); + if (!get_And_Validate_Integer_Input_I(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FAST_FORMAT_FLAG)) + { + print_Error_In_Cmd_Line_Args(FAST_FORMAT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING) == 0) { ATA_SECURITY_FORCE_SAT_VALID = true; if (strcmp(optarg, "enable") == 0) @@ -572,7 +609,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_ERASE_OP_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING) == 0) { ATA_SECURITY_ERASE_OP = true; if (strcmp(optarg, "enhanced") == 0) @@ -591,7 +628,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "master") == 0) { @@ -608,7 +645,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_PASSWORD_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_LONG_OPT_STRING) == 0) { ATA_SECURITY_USER_PROVIDED_PASS = true; if (strcmp(optarg, "empty") == 0) @@ -619,24 +656,23 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(optarg, "SeaChest") == 0) { - ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, strlen("SeaChest")); - memcpy(ATA_SECURITY_PASSWORD, "SeaChest", strlen("SeaChest")); + ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, safe_strlen("SeaChest")); + memcpy(ATA_SECURITY_PASSWORD, "SeaChest", safe_strlen("SeaChest")); } else { //If the user quoted their password when putting on the cmdline, then we can accept spaces. Otherwise spaces cannot be picked up. - //TODO: If comma separated values were given, then we need to parse the input differently!!! - if (strlen(optarg) > ATA_SECURITY_MAX_PW_LENGTH) + if (safe_strlen(optarg) > ATA_SECURITY_MAX_PW_LENGTH) { print_Error_In_Cmd_Line_Args(ATA_SECURITY_PASSWORD_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } //printf("User entered \"%s\" for their password\n", optarg); - memcpy(ATA_SECURITY_PASSWORD, optarg, M_Min(strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH));//make sure we don't try copying over a null terminator because we just need to store the 32bytes of characters provided. - ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, M_Min(strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH)); + safe_memcpy(ATA_SECURITY_PASSWORD, 32, optarg, safe_strlen(optarg));//make sure we don't try copying over a null terminator because we just need to store the 32bytes of characters provided. + ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, M_Min(safe_strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH)); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "byteswap") == 0) { @@ -720,7 +756,7 @@ int32_t main(int argc, char *argv[]) ATA_SECURITY_PASSWORD_MODIFICATIONS.md5Hash = true; } #endif - //TODO: handle other modifications + //handle other modifications //TODO: handle bad combinations of modifications else { @@ -728,22 +764,22 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -758,51 +794,71 @@ int32_t main(int argc, char *argv[]) else { char *colonLocation = strstr(optarg, ":") + 1;//adding 1 to offset just beyond the colon for parsing the remaining data - if (strncmp("file:", optarg, 5) == 0) - { - FILE *patternFile = NULL; - size_t filenameLength = strlen(colonLocation) + 1; - char *filename = C_CAST(char*, calloc(filenameLength, sizeof(char))); - if (!filename) + if (colonLocation && strncmp("file:", optarg, 5) == 0) + { + fileExt allowedExt[] = { + {".bin", false}, + {".BIN", false}, + {M_NULLPTR, false} }; + secureFileInfo* fileinfo = secure_Open_File(colonLocation, "rb", allowedExt, M_NULLPTR, M_NULLPTR); + if (fileinfo) { - exit(UTIL_EXIT_CANNOT_OPEN_FILE); - } - snprintf(filename, filenameLength, "%s", colonLocation); - //open file - if (NULL == (patternFile = fopen(filename, "rb"))) - { - printf("Unable to open file \"%s\" for pattern\n", filename); - exit(UTIL_EXIT_CANNOT_OPEN_FILE); + if (fileinfo->error == SEC_FILE_SUCCESS) + { + if (SEC_FILE_SUCCESS != secure_Read_File(fileinfo, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH, sizeof(uint8_t), fileinfo->fileSize, M_NULLPTR)) + { + printf("Unable to read contents of the file \"%s\" for the pattern.\n", fileinfo->filename); + if (SEC_FILE_SUCCESS != secure_Close_File(fileinfo)) + { + printf("secure file structure could not be closed! This is a fatal error!\n"); + } + free_Secure_File_Info(&fileinfo); + exit(UTIL_EXIT_CANNOT_OPEN_FILE); + } + } + else + { + printf("Unable to open file \"%s\" for pattern\n", colonLocation); + exit(UTIL_EXIT_CANNOT_OPEN_FILE); + } + if (SEC_FILE_SUCCESS != secure_Close_File(fileinfo)) + { + printf("secure file structure could not be closed! This is a fatal error!\n"); + } + free_Secure_File_Info(&fileinfo); } - //read contents into buffer - if (0 == fread(PATTERN_BUFFER, sizeof(uint8_t), M_Min(PATTERN_BUFFER_LENGTH, get_File_Size(patternFile)), patternFile)) + else { - printf("Unable to read contents of the file \"%s\" for the pattern.\n", filename); - fclose(patternFile); + printf("Unable to open file \"%s\" for pattern\n", colonLocation); exit(UTIL_EXIT_CANNOT_OPEN_FILE); } - //close file - fclose(patternFile); - safe_Free(filename); } - else if (strncmp("increment:", optarg, 10) == 0) + else if (colonLocation && strncmp("increment:", optarg, 10) == 0) { - uint8_t incrementStart = C_CAST(uint8_t, atoi(colonLocation)); - fill_Incrementing_Pattern_In_Buffer(incrementStart, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); + uint8_t incrementStart = 0; + if (get_And_Validate_Integer_Input_Uint8(colonLocation, M_NULLPTR, ALLOW_UNIT_NONE, &incrementStart)) + { + fill_Incrementing_Pattern_In_Buffer(incrementStart, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); + } + else + { + print_Error_In_Cmd_Line_Args(PATTERN_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp("repeat:", optarg, 7) == 0) + else if (colonLocation && strncmp("repeat:", optarg, 7) == 0) { //if final character is a lower case h, it's an hex pattern - if (colonLocation[strlen(colonLocation) - 1] == 'h' && strlen(colonLocation) == 9) + if (colonLocation[safe_strlen(colonLocation) - 1] == 'h' && safe_strlen(colonLocation) == 9) { - uint32_t hexPattern = C_CAST(uint32_t, strtoul(colonLocation, NULL, 16)); + uint32_t hexPattern = C_CAST(uint32_t, strtoul(colonLocation, M_NULLPTR, 16)); //TODO: add endianness check before byte swap byte_Swap_32(&hexPattern); fill_Hex_Pattern_In_Buffer(hexPattern, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); } else { - fill_ASCII_Pattern_In_Buffer(colonLocation, C_CAST(uint32_t, strlen(colonLocation)), PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); + fill_ASCII_Pattern_In_Buffer(colonLocation, C_CAST(uint32_t, safe_strlen(colonLocation)), PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); } } else @@ -812,7 +868,7 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, ZERO_VERIFY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ZERO_VERIFY_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ZERO_VERIFY_LONG_OPT_STRING) == 0) { ZERO_VERIFY_FLAG = true; if (strcmp(optarg, "full") == 0) @@ -829,6 +885,14 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } + else if (strcmp(longopts[optionIndex].name, SANITIZE_OVERWRITE_PASSES_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SANITIZE_OVERWRITE_PASSES)) + { + print_Error_In_Cmd_Line_Args(SANITIZE_OVERWRITE_PASSES_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } break; case PROGRESS_SHORT_OPT: //get test progress for a specific test PROGRESS_CHAR = optarg; @@ -858,9 +922,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -886,7 +951,40 @@ int32_t main(int argc, char *argv[]) } exit(UTIL_EXIT_NO_ERROR); case 'e': //sanitize - SANITIZE_SUBOPT_PARSE + if (strcmp(SANITIZE_BLOCK_ERASE_STR, optarg) == 0) + { + SANITIZE_RUN_FLAG = true; + SANITIZE_RUN_BLOCK_ERASE = true; + } + else if (strcmp(SANITIZE_CRYPTO_ERASE_STR, optarg) == 0) + { + SANITIZE_RUN_FLAG = true; + SANITIZE_RUN_CRYPTO_ERASE = true; + } + else if (strcmp(SANITIZE_OVERWRITE_ERASE_STR, optarg) == 0) + { + SANITIZE_RUN_FLAG = true; + SANITIZE_RUN_OVERWRITE_ERASE = true; + } + else if (strcmp("freezelock", optarg) == 0) + { + SANITIZE_FREEZE = true; + printf("Please migrate to using --%s as this will be removed in future versions\n", SANITIZE_FREEZE_LONG_OPT_STRING); + } + else if (strcmp("antifreezelock", optarg) == 0) + { + SANITIZE_ANTIFREEZE = true; + printf("Please migrate to using --%s as this will be removed in future versions\n", SANITIZE_ANTIFREEZE_LONG_OPT_STRING); + } + else if (strcmp("info", optarg) == 0) + { + SANITIZE_INFO_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(SANITIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } break; default: break; @@ -900,7 +998,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -931,11 +1029,11 @@ int32_t main(int argc, char *argv[]) print_Elevated_Privileges_Text(); } unsigned int scanControl = DEFAULT_SCAN; - if(AGRESSIVE_SCAN_FLAG) + if (AGRESSIVE_SCAN_FLAG) { scanControl |= AGRESSIVE_SCAN; } - #if defined (__linux__) +#if defined (__linux__) if (SCAN_FLAGS.scanSD) { scanControl |= SD_HANDLES; @@ -944,7 +1042,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SG_TO_SD; } - #endif +#endif //set the drive types to show (if none are set, the lower level code assumes we need to show everything) if (SCAN_FLAGS.scanATA) { @@ -997,7 +1095,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -1016,31 +1114,34 @@ int32_t main(int argc, char *argv[]) if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase) { //change all to uppercase - char thePassword[ATA_SECURITY_MAX_PW_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, thePassword, ATA_SECURITY_MAX_PW_LENGTH + 1); memcpy(thePassword, ATA_SECURITY_PASSWORD, ATA_SECURITY_MAX_PW_LENGTH); convert_String_To_Upper_Case(thePassword); memcpy(ATA_SECURITY_PASSWORD, thePassword, ATA_SECURITY_MAX_PW_LENGTH); + explicit_zeroes(thePassword, ATA_SECURITY_MAX_PW_LENGTH); } else if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase) { //change all to lowercase - char thePassword[ATA_SECURITY_MAX_PW_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, thePassword, ATA_SECURITY_MAX_PW_LENGTH + 1); memcpy(thePassword, ATA_SECURITY_PASSWORD, ATA_SECURITY_MAX_PW_LENGTH); convert_String_To_Lower_Case(thePassword); memcpy(ATA_SECURITY_PASSWORD, thePassword, ATA_SECURITY_MAX_PW_LENGTH); + explicit_zeroes(thePassword, ATA_SECURITY_MAX_PW_LENGTH); } else if (ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) { //swap case from upper to lower and lower to upper. - char thePassword[ATA_SECURITY_MAX_PW_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, thePassword, ATA_SECURITY_MAX_PW_LENGTH + 1); memcpy(thePassword, ATA_SECURITY_PASSWORD, ATA_SECURITY_MAX_PW_LENGTH); convert_String_To_Inverse_Case(thePassword); memcpy(ATA_SECURITY_PASSWORD, thePassword, ATA_SECURITY_MAX_PW_LENGTH); + explicit_zeroes(thePassword, ATA_SECURITY_MAX_PW_LENGTH); } //check if byteswapping what was entered if (ATA_SECURITY_PASSWORD_MODIFICATIONS.byteSwapped) { - for (uint8_t iter = 0; iter < ATA_SECURITY_MAX_PW_LENGTH; iter += 2) + for (uint8_t iter = 0; iter < (ATA_SECURITY_MAX_PW_LENGTH - 1); iter += 2) { uint8_t temp = ATA_SECURITY_PASSWORD[iter + 1]; ATA_SECURITY_PASSWORD[iter + 1] = ATA_SECURITY_PASSWORD[iter]; @@ -1055,7 +1156,7 @@ int32_t main(int argc, char *argv[]) else if (ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned) { //memcpy and memset based on how many characters were provided by the caller. - memmove(&ATA_SECURITY_PASSWORD[ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT], &ATA_SECURITY_PASSWORD[0], ATA_SECURITY_PASSWORD_BYTE_COUNT); + safe_memmove(&ATA_SECURITY_PASSWORD[ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT], ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT, &ATA_SECURITY_PASSWORD[0], ATA_SECURITY_PASSWORD_BYTE_COUNT); memset(&ATA_SECURITY_PASSWORD[0], 0, ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT); } //now check if we had padding to add. NOTE: if right aligned, padding mshould be added IN FRONT (left side) @@ -1096,8 +1197,8 @@ int32_t main(int argc, char *argv[]) else { //user did not set a password, so we need to set "SeaChest" - ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, strlen("SeaChest")); - memcpy(ATA_SECURITY_PASSWORD, "SeaChest", strlen("SeaChest")); + ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, safe_strlen("SeaChest")); + memcpy(ATA_SECURITY_PASSWORD, "SeaChest", safe_strlen("SeaChest")); } //print out errors for unknown arguments for remaining args that haven't been processed yet @@ -1145,6 +1246,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -1169,12 +1272,15 @@ int32_t main(int argc, char *argv[]) || TCG_REVERT_SP_FLAG || TCG_REVERT_FLAG #endif - || sanitize + || SANITIZE_RUN_FLAG + || SANITIZE_FREEZE + || SANITIZE_ANTIFREEZE + || SANITIZE_INFO_FLAG || RUN_WRITE_SAME_FLAG || ATA_SECURITY_ERASE_OP || RUN_OVERWRITE_FLAG || RUN_TRIM_UNMAP_FLAG - || (PROGRESS_CHAR != NULL) + || (PROGRESS_CHAR != M_NULLPTR) || SHOW_ERASE_SUPPORT_FLAG || PERFORM_FASTEST_ERASE_FLAG || FORMAT_UNIT_FLAG @@ -1182,6 +1288,7 @@ int32_t main(int argc, char *argv[]) || NVM_FORMAT_FLAG || ZERO_VERIFY_FLAG || ERASE_RESTORE_MAX_PREP + || REFRESH_FILE_SYSTEMS )) { utility_Usage(true); @@ -1190,7 +1297,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1233,7 +1340,6 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -1281,11 +1387,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -1309,7 +1415,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -1401,7 +1507,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1426,7 +1532,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1466,6 +1572,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1529,10 +1644,10 @@ int32_t main(int argc, char *argv[]) #ifdef DISABLE_TCG_SUPPORT //TODO: Check the return method. get_Supported_Erase_Methods(&deviceList[deviceIter], eraseMethodList, &overwriteTimeMinutes); -#else +#else //!DISABLE_TCG_SUPPORT //get_Supported_Erase_Methods(&selectedDevice, &eraseMethodList);//switch this to method with TCG support later - TJE get_Supported_Erase_Methods_With_TCG(&deviceList[deviceIter], eraseMethodList, &overwriteTimeMinutes); -#endif +#endif //DISABLE_TCG_SUPPORT print_Supported_Erase_Methods(&deviceList[deviceIter], eraseMethodList, &overwriteTimeMinutes); } @@ -1543,7 +1658,7 @@ int32_t main(int argc, char *argv[]) if (DISPLAY_LBA_FLAG) { - uint8_t *displaySector = C_CAST(uint8_t*, calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t *displaySector = C_CAST(uint8_t*, safe_calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (!displaySector) { perror("Could not allocate memory to read LBA."); @@ -1559,15 +1674,15 @@ int32_t main(int argc, char *argv[]) } if (SUCCESS == read_LBA(&deviceList[deviceIter], DISPLAY_LBA_THE_LBA, false, displaySector, deviceList[deviceIter].drive_info.deviceBlockSize)) { - printf("\nContents of LBA %"PRIu64":\n", DISPLAY_LBA_THE_LBA); + printf("\nContents of LBA %" PRIu64 ":\n", DISPLAY_LBA_THE_LBA); print_Data_Buffer(displaySector, deviceList[deviceIter].drive_info.deviceBlockSize, false); } else { - printf("Error Reading LBA %"PRIu64" for display\n", DISPLAY_LBA_THE_LBA); + printf("Error Reading LBA %" PRIu64 " for display\n", DISPLAY_LBA_THE_LBA); exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(displaySector) + safe_free_aligned(&displaySector); } //check for fastest erase flag first since it may be used to set other flags for other erase methods @@ -1579,10 +1694,10 @@ int32_t main(int argc, char *argv[]) eraseMethod eraseMethodList[MAX_SUPPORTED_ERASE_METHODS]; #ifdef DISABLE_TCG_SUPPORT //TODO: Check the return method. - get_Supported_Erase_Methods(&deviceList[deviceIter], eraseMethodList, NULL); + get_Supported_Erase_Methods(&deviceList[deviceIter], eraseMethodList, M_NULLPTR); #else //get_Supported_Erase_Methods(&selectedDevice, &eraseMethodList);//switch this to method with TCG support later - TJE - get_Supported_Erase_Methods_With_TCG(&deviceList[deviceIter], eraseMethodList, NULL); + get_Supported_Erase_Methods_With_TCG(&deviceList[deviceIter], eraseMethodList, M_NULLPTR); #endif switch (eraseMethodList[0].eraseIdentifier) @@ -1599,16 +1714,16 @@ int32_t main(int argc, char *argv[]) break; #endif case ERASE_SANITIZE_OVERWRITE: - sanitize = true; - sanoverwrite = true; + SANITIZE_RUN_FLAG = true; + SANITIZE_RUN_OVERWRITE_ERASE = true; break; case ERASE_SANITIZE_BLOCK: - sanitize = true; - sanblockErase = true; + SANITIZE_RUN_FLAG = true; + SANITIZE_RUN_BLOCK_ERASE = true; break; case ERASE_SANITIZE_CRYPTO: - sanitize = true; - sancryptoErase = true; + SANITIZE_RUN_FLAG = true; + SANITIZE_RUN_CRYPTO_ERASE = true; break; case ERASE_NVM_FORMAT_USER_SECURE_ERASE: NVM_FORMAT_FLAG = true; @@ -1671,9 +1786,12 @@ int32_t main(int argc, char *argv[]) fill_Drive_Info_Data(&deviceList[deviceIter]);//refresh stale data if (VERBOSITY_QUIET < toolVerbosity) { - double mCapacity = 0, capacity = 0; - char mCapUnits[UNIT_STRING_LENGTH] = { 0 }, capUnits[UNIT_STRING_LENGTH] = { 0 }; - char* mCapUnit = &mCapUnits[0], * capUnit = &capUnits[0]; + double mCapacity = 0; + double capacity = 0; + DECLARE_ZERO_INIT_ARRAY(char, mCapUnits, UNIT_STRING_LENGTH); + DECLARE_ZERO_INIT_ARRAY(char, capUnits, UNIT_STRING_LENGTH); + char* mCapUnit = &mCapUnits[0]; + char* capUnit = &capUnits[0]; if (deviceList[deviceIter].drive_info.bridge_info.isValid) { mCapacity = C_CAST(double, deviceList[deviceIter].drive_info.bridge_info.childDeviceMaxLba * deviceList[deviceIter].drive_info.bridge_info.childDeviceBlockSize); @@ -1717,7 +1835,15 @@ int32_t main(int argc, char *argv[]) printf("remove the --%s option from the command line and try again.\n", ERASE_RESTORE_MAX_PREP_LONG_OPT_STRING); printf("Erase will not be started while this is failing.\n\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; + exitCode = UTIL_EXIT_OPERATION_ABORTED; + break; + case POWER_CYCLE_REQUIRED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("The device requires a power cycle before the max LBA can be restored all the way.\n"); + printf("Please power cycle the device, then run the --%s option again.\n", ERASE_RESTORE_MAX_PREP_LONG_OPT_STRING); + } + exitCode = UTIL_EXIT_OPERATION_ABORTED; break; case NOT_SUPPORTED: if (VERBOSITY_QUIET < toolVerbosity) @@ -1766,7 +1892,9 @@ int32_t main(int argc, char *argv[]) } if (DATA_ERASE_FLAG) { - if (strlen(TCG_PSID_FLAG) == 0) + writeAfterErase writeReq; + memset(&writeReq, 0, sizeof(writeAfterErase)); + if (safe_strlen(TCG_PSID_FLAG) == 0) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1774,7 +1902,7 @@ int32_t main(int argc, char *argv[]) } return UTIL_EXIT_ERROR_IN_COMMAND_LINE; } - else if (strlen(TCG_PSID_FLAG) < 32) + else if (safe_strlen(TCG_PSID_FLAG) < 32) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1792,6 +1920,17 @@ int32_t main(int argc, char *argv[]) { printf("NOTE: This command may have affected more than 1 logical unit\n"); } + if (writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + { + printf("ADVISORY: This device requires a write to all LBAs after a crypto erase!\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); + } + } + eraseCompleted = true; + if (writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + { + eraseCompleted = false;//turn this off otherwise the function to update file systems outputs errors to the screen since it tries to read the device. } eraseCompleted = true; break; @@ -1836,12 +1975,14 @@ int32_t main(int argc, char *argv[]) } if (DATA_ERASE_FLAG) { + writeAfterErase writeReq; eRevertAuthority authority = REVERT_AUTHORITY_MSID; - char *passwordToUse = NULL; - if (strlen(TCG_PSID_FLAG) || strlen(TCG_SID_FLAG)) + char *passwordToUse = M_NULLPTR; + memset(&writeReq, 0, sizeof(writeAfterErase)); + if (safe_strlen(TCG_PSID_FLAG) || safe_strlen(TCG_SID_FLAG)) { //user is providing SID or PSID to use. - if (strlen(TCG_PSID_FLAG) > 0 && strlen(TCG_PSID_FLAG) < 32) + if (safe_strlen(TCG_PSID_FLAG) > 0 && safe_strlen(TCG_PSID_FLAG) < 32) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1849,12 +1990,12 @@ int32_t main(int argc, char *argv[]) } return UTIL_EXIT_ERROR_IN_COMMAND_LINE; } - else if (strlen(TCG_PSID_FLAG) == 32) + else if (safe_strlen(TCG_PSID_FLAG) == 32) { authority = REVERT_AUTHORITY_PSID; passwordToUse = TCG_PSID_FLAG; } - else if (strlen(TCG_SID_FLAG) > 0) + else if (safe_strlen(TCG_SID_FLAG) > 0) { authority = REVERT_AUTHORITY_SID; passwordToUse = TCG_SID_FLAG; @@ -1876,6 +2017,12 @@ int32_t main(int argc, char *argv[]) printf("\tNOTE: Because the lockingSP was not activated, the user data may not have been erased.\n"); printf("\t Run a cryptographic erase, such as Sanitize cryptoerase to ensure data was completely erased.\n\n"); } + if (writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + { + printf("ADVISORY: This device requires a write to all LBAs after a crypto erase!\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); + } if (deviceList[deviceIter].drive_info.numberOfLUs > 1) { printf("NOTE: This command may have affected more than 1 logical unit\n"); @@ -1885,6 +2032,10 @@ int32_t main(int argc, char *argv[]) { eraseCompleted = true; } + if (writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + { + eraseCompleted = false;//turn this off otherwise the function to update file systems outputs errors to the screen since it tries to read the device. + } break; case NOT_SUPPORTED: if (VERBOSITY_QUIET < toolVerbosity) @@ -1923,7 +2074,7 @@ int32_t main(int argc, char *argv[]) if (ZERO_VERIFY_FLAG) { - ret = zero_Verify_Test(&deviceList[deviceIter], ZERO_VERIFY_MODE_FLAG, HIDE_LBA_COUNTER); + ret = zero_Verify_Test(&deviceList[deviceIter], C_CAST(eZeroVerifyTestType, ZERO_VERIFY_MODE_FLAG), HIDE_LBA_COUNTER); switch (ret) { case SUCCESS: @@ -1949,288 +2100,437 @@ int32_t main(int argc, char *argv[]) } } - if (sanitize) + if (SANITIZE_FREEZE) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sending Sanitize Freeze Lock Command.\n"); + } + switch (sanitize_Freezelock(&deviceList[deviceIter])) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize Freezelock passed!\n"); + } + break; + case FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize Freezelock failed!\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize Freezelock not supported.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case IN_PROGRESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("A Sanitize operation is already in progress, freezelock cannot be completed.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + case DEVICE_ACCESS_DENIED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Access Denied while attempting Sanitize. Please make sure security has unlocked the drive and try again.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unknown error in sanitize command.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (SANITIZE_ANTIFREEZE) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sending Sanitize Anti Freeze Lock Command.\n"); + } + switch (sanitize_Anti_Freezelock(&deviceList[deviceIter])) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize Anti Freezelock passed!\n"); + } + break; + case FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize Anti Freezelock failed!\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize Anti Freezelock not supported.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case IN_PROGRESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("A Sanitize operation is already in progress, anti freezelock cannot be completed.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + case DEVICE_ACCESS_DENIED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Access Denied while attempting Sanitize. Please make sure security has unlocked the drive and try again.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unknown error in sanitize command.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + if (SANITIZE_INFO_FLAG) { - int sanitizeResult = UNKNOWN; sanitizeFeaturesSupported sanitizeOptions; memset(&sanitizeOptions, 0, sizeof(sanitizeFeaturesSupported)); - sanitizeResult = get_Sanitize_Device_Features(&deviceList[deviceIter], &sanitizeOptions); if (VERBOSITY_QUIET < toolVerbosity) { - printf("\nSanitize\n"); + printf("\nSanitize Info\n"); } - if (sanitizeInfo) + if (SUCCESS == get_Sanitize_Device_Features(&deviceList[deviceIter], &sanitizeOptions)) { - if (SUCCESS == sanitizeResult) + if (sanitizeOptions.sanitizeCmdEnabled) { - if (sanitizeOptions.crypto || sanitizeOptions.blockErase || sanitizeOptions.overwrite) + printf("\tThe following sanitize commands are supported:\n"); + if (sanitizeOptions.crypto) { - printf("\tThe following sanitize commands are supported:\n"); - if (sanitizeOptions.crypto) - { - printf("\t\tCrypto Erase\t--%s cryptoerase\n", SANITIZE_LONG_OPT_STRING); - } - if (sanitizeOptions.blockErase) + printf("\t\tCrypto Erase\t--%s cryptoerase\n", SANITIZE_LONG_OPT_STRING); + } + if (sanitizeOptions.writeAfterCryptoErase >= WAEREQ_MEDIUM_ERROR_OTHER_ASC) + { + if (sanitizeOptions.writeAfterCryptoErase == WAEREQ_PI_FORMATTED_MAY_REQUIRE_OVERWRITE) { - printf("\t\tBlock Erase\t--%s blockerase\n", SANITIZE_LONG_OPT_STRING); + printf("\t\t\tWrite after crypto erase may be required due to PI formatting! Reads may return an error until written!\n"); } - if (sanitizeOptions.overwrite) + else { - printf("\t\tOverwrite\t--%s overwrite\n", SANITIZE_LONG_OPT_STRING); + printf("\t\t\tWrite after crypto erase required! Reads will return an error until written!\n"); } } - else + if (sanitizeOptions.blockErase) { - printf("\tSanitize commands are not supported by this device.\n"); + printf("\t\tBlock Erase\t--%s blockerase\n", SANITIZE_LONG_OPT_STRING); } - } - else - { - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("\tSanitize Features not supported.\n"); - } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; - } - } - //if sanitize features are supported and the user has input a sanitize command to run, then we can kick them off - if (sanitizeOptions.sanitizeCmdEnabled) - { - if (DATA_ERASE_FLAG && !(sanfreezelock || sanAntiFreezeLock || sanitizeInfo)) - { - bool sanitizeCommandRun = false; - if (sanblockErase) + if (sanitizeOptions.writeAfterBlockErase >= WAEREQ_MEDIUM_ERROR_OTHER_ASC) { - if (VERBOSITY_QUIET < toolVerbosity) + if (sanitizeOptions.writeAfterCryptoErase == WAEREQ_PI_FORMATTED_MAY_REQUIRE_OVERWRITE) { - printf("Starting Sanitize Block Erase\n"); + printf("\t\t\tWrite after block erase may be required due to PI formatting! Reads may return an error until written!\n"); } - sanitizeResult = run_Sanitize_Operation(&deviceList[deviceIter], SANITIZE_BLOCK_ERASE, POLL_FLAG, NULL, 0); - sanitizeCommandRun = true; - } - if (sancryptoErase) - { - if (VERBOSITY_QUIET < toolVerbosity) + else { - printf("Starting Sanitize Crypto Scramble\n"); + printf("\t\t\tWrite after block erase required! Reads will return an error until written!\n"); } - sanitizeResult = run_Sanitize_Operation(&deviceList[deviceIter], SANITIZE_CRYPTO_ERASE, POLL_FLAG, NULL, 0); - sanitizeCommandRun = true; } - if (sanoverwrite) + if (sanitizeOptions.overwrite) { - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Starting Sanitize Overwrite Erase\n"); - } - sanitizeResult = run_Sanitize_Operation(&deviceList[deviceIter], SANITIZE_OVERWRITE_ERASE, POLL_FLAG, PATTERN_BUFFER, deviceList[deviceIter].drive_info.deviceBlockSize); - sanitizeCommandRun = true; + printf("\t\tOverwrite\t--%s overwrite\n", SANITIZE_LONG_OPT_STRING); + printf("\t\t\tMaximum overwrite passes: %" PRIu8 "\n", sanitizeOptions.maximumOverwritePasses); + } + if (sanitizeOptions.freezelock) + { + printf("\t\tFreezelock\t--%s\n", SANITIZE_FREEZE_LONG_OPT_STRING); + } + if (sanitizeOptions.antiFreezeLock) + { + printf("\t\tAntifreezelock\t--%s\n", SANITIZE_ANTIFREEZE_LONG_OPT_STRING); } - if (sanitizeCommandRun) + if (sanitizeOptions.noDeallocateInhibited) { - switch (sanitizeResult) + printf("\t\tNo Deallocate Inhibited by controller.\n"); + switch (sanitizeOptions.responseMode) { - case SUCCESS: - if (VERBOSITY_QUIET < toolVerbosity) - { - if (POLL_FLAG) - { - printf("Sanitize command passed!\n"); - } - else - { - printf("Sanitize command has been started. Use the --%s sanitize option\n", PROGRESS_LONG_OPT_STRING); - printf("to check for progress.\n"); - } - if (deviceList[deviceIter].drive_info.numberOfLUs > 1) - { - printf("NOTE: This command may have affected more than 1 logical unit\n"); - } - } - if (sanitizeCommandRun && POLL_FLAG) - { - eraseCompleted = true; - } + case NO_DEALLOC_RESPONSE_INV: break; - case FAILURE: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Sanitize command failed!\n"); - #if defined (_WIN32)//TODO: handle Win PE somehow when we support WinPE - printf("\tNote: Windows 8 and higher block sanitize commands.\n"); - #endif - } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - case IN_PROGRESS: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("A sanitize command is already in progress.\n"); - } - break; - case FROZEN: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Cannot run sanitize operation because drive is sanitize frozen.\n"); - } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Sanitize command not supported by the device.\n"); - } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; - break; - case OS_PASSTHROUGH_FAILURE: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Sanitize command was blocked by the OS.\n"); - #if defined (_WIN32)//TODO: handle Win PE somehow when we support WinPE - printf("\tNote: Windows 8 and higher block sanitize commands.\n"); - #endif - } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + case NO_DEALLOC_RESPONSE_WARNING: + printf("\t\t\tSanitize command will be accepted but warn about deallocation when no deallocate is specified.\n"); break; - case DEVICE_ACCESS_DENIED: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Access Denied while attempting Sanitize. Please make sure security has unlocked the drive and try again.\n"); - } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - default: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Unknown error in sanitize command.\n"); - } - exitCode = UTIL_EXIT_OPERATION_FAILURE; + case NO_DEALLOC_RESPONSE_ERROR: + printf("\t\t\tSanitize command will be aborted with an error when no deallocate is specified.\n"); break; } } + switch (sanitizeOptions.nodmmas) + { + case NODMMAS_NOT_DEFINED: + break; + case NODMMAS_NOT_ADDITIONALLY_MODIFIED_AFTER_SANITIZE: + printf("\t\tMedia does not have additional modifications after sanitize completes.\n"); + break; + case NODMMAS_MEDIA_MODIFIED_AFTER_SANITIZE: + printf("\t\tMedia is modified after sanitize completes.\n"); + break; + case NODMMAS_RESERVED: + break; + } + } - else if (sanfreezelock) + else + { + printf("\tSanitize commands are not supported by this device.\n"); + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tSanitize Features not supported.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } + } + + if (SANITIZE_RUN_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\nSanitize\n"); + } + if (DATA_ERASE_FLAG) + { + bool sanitizeCommandRun = false; + sanitizeOperationOptions sanitizeOp; + memset(&sanitizeOp, 0, sizeof(sanitizeOperationOptions)); + sanitizeOp.version = SANITIZE_OPERATION_OPTIONS_VERSION; + sanitizeOp.size = sizeof(sanitizeOperationOptions); + sanitizeOp.pollForProgress = POLL_FLAG; + sanitizeOp.commonOptions.allowUnrestrictedSanitizeExit = SANITIZE_AUSE; + //NOTE: The next two options are in a union to mean the same thing + // It is likely that a user will specify one for NVMe devices and one for SATA/SAS + // So if this is specified, keep the one set to true. + sanitizeOp.commonOptions.zoneNoReset = ZONE_NO_RESET; + if (!sanitizeOp.commonOptions.noDeallocate) + { + sanitizeOp.commonOptions.noDeallocate = NO_DEALLOCATE_AFTER_ERASE; + } + if (SANITIZE_RUN_BLOCK_ERASE) { if (VERBOSITY_QUIET < toolVerbosity) { - printf("Sending Sanitize Freeze Lock Command.\n"); + printf("Starting Sanitize Block Erase\n"); } - sanitizeResult = run_Sanitize_Operation(&deviceList[deviceIter], SANTIZIE_FREEZE_LOCK, false, NULL, 0); - switch (sanitizeResult) + sanitizeOp.sanitizeEraseOperation = BLOCK_ERASE; + } + if (SANITIZE_RUN_CRYPTO_ERASE) + { + if (VERBOSITY_QUIET < toolVerbosity) { - case SUCCESS: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Sanitize Freezelock passed!\n"); - } - break; - case FAILURE: - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Sanitize Freezelock failed!\n"); - } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) + printf("Starting Sanitize Crypto Scramble\n"); + } + sanitizeOp.sanitizeEraseOperation = CRYPTO_ERASE; + } + if (SANITIZE_RUN_OVERWRITE_ERASE) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Starting Sanitize Overwrite Erase\n"); + } + sanitizeOp.sanitizeEraseOperation = OVERWRITE_ERASE; + sanitizeOp.overwriteOptions.invertPatternBetweenPasses = SANITIZE_IPBP; + sanitizeOp.overwriteOptions.numberOfPasses = SANITIZE_OVERWRITE_PASSES; + if (PATTERN_FLAG) + { + sanitizeOp.overwriteOptions.pattern = M_BytesTo4ByteValue(patternBuffer[3], patternBuffer[2], patternBuffer[1], patternBuffer[0]); + } + } + //get the support information before starting sanitize to add warnings about write after block erase or write after crypto erase. + writeAfterErase writeReq; + memset(&writeReq, 0, sizeof(writeAfterErase)); + is_Write_After_Erase_Required(&deviceList[deviceIter], &writeReq); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("If Sanitize appears to be taking much longer than expected, the system or HBA\n"); + printf("may not be handling the sanitize in progress state correctly. If this happens\n"); + printf("the next best thing to do is leave the drive powered on with the interface\n"); + printf("cable(SATA / SAS HBA cable) disconnected. Sanitize will continue running\n"); + printf("while the drive is powered onand the system will no longer be able to\n"); + printf("interrupt or slow down the sanitize operation.\n"); + printf("NOTE: On an HDD, the approximate overwrite time is 1.5-2 hours per terabyte\n"); + printf(" of the native capacity of the drive. Reduced size for maxLBA does not\n"); + printf(" reduce the time sanitize takes to overwrite the drive.\n"); + printf(" On an SSD, the overwrite time will be much faster and varies depending\n"); + printf(" on the capabilities of the SSD controller.\n\n"); + if (SANITIZE_RUN_BLOCK_ERASE && writeReq.blockErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + { + if (writeReq.blockErase == WAEREQ_PI_FORMATTED_MAY_REQUIRE_OVERWRITE) { - printf("Sanitize Freezelock not supported.\n"); + printf("ADVISORY: This device may require a write to all LBAs after a crypto erase!\n"); + printf(" PI bytes may be invalid and reading them results in logical block guard\n"); + printf(" check failures until a logical block has been written with new data.\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; - break; - case IN_PROGRESS: - if (VERBOSITY_QUIET < toolVerbosity) + else { - printf("A Sanitize operation is already in progress, freezelock cannot be completed.\n"); + printf("ADVISORY: This device requires a write to all LBAs after a block erase!\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - case DEVICE_ACCESS_DENIED: - if (VERBOSITY_QUIET < toolVerbosity) + } + if (SANITIZE_RUN_CRYPTO_ERASE && writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + { + if (writeReq.blockErase == WAEREQ_PI_FORMATTED_MAY_REQUIRE_OVERWRITE) { - printf("Access Denied while attempting Sanitize. Please make sure security has unlocked the drive and try again.\n"); + printf("ADVISORY: This device may require a write to all LBAs after a crypto erase!\n"); + printf(" PI bytes may be scrambled and reading them results in logical block guard\n"); + printf(" check failures until a logical block has been written with new data.\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - default: - if (VERBOSITY_QUIET < toolVerbosity) + else { - printf("Unknown error in sanitize command.\n"); + printf("ADVISORY: This device requires a write to all LBAs after a crypto erase!\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; } } - else if (sanAntiFreezeLock) + switch (run_Sanitize_Operation2(&deviceList[deviceIter], sanitizeOp)) { + case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Sending Sanitize Anti Freeze Lock Command.\n"); - } - sanitizeResult = run_Sanitize_Operation(&deviceList[deviceIter], SANITIZE_ANTI_FREEZE_LOCK, false, NULL, 0); - switch (sanitizeResult) - { - case SUCCESS: - if (VERBOSITY_QUIET < toolVerbosity) + if (POLL_FLAG) { - printf("Sanitize Anti Freezelock passed!\n"); + printf("Sanitize command passed!\n"); } - break; - case FAILURE: - if (VERBOSITY_QUIET < toolVerbosity) + else { - printf("Sanitize Anti Freezelock failed!\n"); + printf("Sanitize command has been started. Use the --%s sanitize option\n", PROGRESS_LONG_OPT_STRING); + printf("to check for progress.\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) + if (deviceList[deviceIter].drive_info.numberOfLUs > 1) { - printf("Sanitize Anti Freezelock not supported.\n"); + printf("NOTE: This command may have affected more than 1 logical unit\n"); } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; - break; - case IN_PROGRESS: - if (VERBOSITY_QUIET < toolVerbosity) + if (SANITIZE_RUN_BLOCK_ERASE && writeReq.blockErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) { - printf("A Sanitize operation is already in progress, anti freezelock cannot be completed.\n"); + printf("ADVISORY: This device requires a write to all LBAs after a block erase!\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - case DEVICE_ACCESS_DENIED: - if (VERBOSITY_QUIET < toolVerbosity) + if (SANITIZE_RUN_CRYPTO_ERASE && writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) { - printf("Access Denied while attempting Sanitize. Please make sure security has unlocked the drive and try again.\n"); + printf("ADVISORY: This device requires a write to all LBAs after a crypto erase!\n"); + printf(" Attempting to read any LBA will result in a failure until it\n"); + printf(" has been written with new data!\n\n"); } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; - default: - if (VERBOSITY_QUIET < toolVerbosity) + } + if (sanitizeCommandRun && POLL_FLAG) + { + eraseCompleted = true; + if ((SANITIZE_RUN_BLOCK_ERASE && writeReq.blockErase > WAEREQ_READ_COMPLETES_GOOD_STATUS) + || (SANITIZE_RUN_CRYPTO_ERASE && writeReq.cryptoErase > WAEREQ_READ_COMPLETES_GOOD_STATUS)) { - printf("Unknown error in sanitize command.\n"); + eraseCompleted = false;//turn this off otherwise the function to update file systems outputs errors to the screen since it tries to read the device. } - exitCode = UTIL_EXIT_OPERATION_FAILURE; - break; } - } - else if (!sanitizeInfo) - { + break; + case FAILURE: if (VERBOSITY_QUIET < toolVerbosity) { - printf("\n"); - printf("You must add the flag:\n\"%s\" \n", DATA_ERASE_ACCEPT_STRING); - printf("to the command line arguments to run a sanitize operation.\n\n"); - printf("e.g.: %s -d %s --%s blockerase --confirm %s\n\n", util_name, deviceHandleExample, SANITIZE_LONG_OPT_STRING, DATA_ERASE_ACCEPT_STRING); + printf("Sanitize command failed!\n"); + #if defined (_WIN32) + if (!is_Windows_PE()) + { + printf("\tNote: Windows 8 and higher block sanitize commands.\n"); + printf("\t Starting in Windows 11 or Windows 10 21H2, NVMe\n"); + printf("\t devices can issue Sanitize Block or Crypto erases\n"); + printf("\t but no other device types or sanitize operations\n"); + printf("\t are permitted.\n"); + printf("\t The Windows PE/RE environments allow all sanitize operations.\n"); + } + #endif //_WIN32 + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + case IN_PROGRESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("A sanitize command is already in progress.\n"); + } + break; + case FROZEN: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Cannot run sanitize operation because drive is sanitize frozen.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize command not supported by the device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case OS_PASSTHROUGH_FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Sanitize command was blocked by the OS.\n"); +#if defined (_WIN32) + if (!is_Windows_PE()) + { + printf("\tNote: Windows 8 and higher block sanitize commands.\n"); + printf("\t Starting in Windows 11 or Windows 10 21H2, NVMe\n"); + printf("\t devices can issue Sanitize Block or Crypto erases\n"); + printf("\t but no other device types or sanitize operations\n"); + printf("\t are permitted.\n"); + printf("\t The Windows PE/RE environments allow all sanitize operations.\n"); + } +#endif //_WIN32 + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case DEVICE_ACCESS_DENIED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Access Denied while attempting Sanitize. Please make sure security has unlocked the drive and try again.\n"); } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unknown error in sanitize command.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; } } - else if (!sanitizeInfo) + else { if (VERBOSITY_QUIET < toolVerbosity) { - printf("\tSanitize Features not supported.\n"); + printf("\n"); + printf("You must add the flag:\n\"%s\" \n", DATA_ERASE_ACCEPT_STRING); + printf("to the command line arguments to run a sanitize operation.\n\n"); + printf("e.g.: %s -d %s --%s blockerase --confirm %s\n\n", util_name, deviceHandleExample, SANITIZE_LONG_OPT_STRING, DATA_ERASE_ACCEPT_STRING); } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; } } @@ -2249,14 +2549,14 @@ int32_t main(int argc, char *argv[]) { currentBlockSize = false; } - formatUnitParameters.formatType = FAST_FORMAT_FLAG; + formatUnitParameters.formatType = C_CAST(eFormatType, FAST_FORMAT_FLAG); if (FAST_FORMAT_FLAG > 0) { formatUnitParameters.disableImmediate = true;//for fast format, we want to hold the bus busy until it is done. } formatUnitParameters.currentBlockSize = currentBlockSize; formatUnitParameters.newBlockSize = FORMAT_SECTOR_SIZE; - formatUnitParameters.gList = NULL; + formatUnitParameters.gList = M_NULLPTR; formatUnitParameters.glistSize = 0; formatUnitParameters.completeList = false; formatUnitParameters.disablePrimaryList = false; @@ -2272,7 +2572,7 @@ int32_t main(int argc, char *argv[]) formatUnitParameters.defaultFormat = false;//This is true unless we need to write a pattern!! } formatUnitParameters.securityInitialize = false; - int formatRet = UNKNOWN; + eReturnValues formatRet = UNKNOWN; os_Lock_Device(&deviceList[deviceIter]); os_Unmount_File_Systems_On_Device(&deviceList[deviceIter]); if (PATTERN_FLAG) @@ -2445,7 +2745,7 @@ int32_t main(int argc, char *argv[]) default: break; } - int formatRet = run_NVMe_Format(&deviceList[deviceIter], nvmformatParameters, POLL_FLAG); + eReturnValues formatRet = run_NVMe_Format(&deviceList[deviceIter], nvmformatParameters, POLL_FLAG); switch (formatRet) { case SUCCESS: @@ -2521,6 +2821,14 @@ int32_t main(int argc, char *argv[]) ataPassword.passwordType = ATA_SECURITY_USING_MASTER_PW; memcpy(ataPassword.password, ATA_SECURITY_PASSWORD, ATA_SECURITY_PASSWORD_BYTE_COUNT);//ATA_SECURITY_PASSWORD_BYTE_COUNT shouldn't ever be > 32. Should be caught above. ataPassword.passwordLength = ATA_SECURITY_PASSWORD_BYTE_COUNT; + if (ZONE_NO_RESET == goTrue) + { + ataPassword.zacSecurityOption = ATA_ZAC_ERASE_FULL_ZONES; + } + else + { + ataPassword.zacSecurityOption = ATA_ZAC_ERASE_EMPTY_ZONES; + } eATASecurityEraseType ataSecureEraseType = ATA_SECURITY_ERASE_STANDARD_ERASE; if (ATA_SECURITY_ERASE_ENHANCED_FLAG) { @@ -2586,7 +2894,7 @@ int32_t main(int argc, char *argv[]) } if (DATA_ERASE_FLAG) { - int writeSameRet = UNKNOWN; + eReturnValues writeSameRet = UNKNOWN; //NOTE: Changed to automatically setting poll, since write same on SATA is EASILY interrupted by anything other than reading the SCT status log...which is a pain since // the OS may issue commands when opening the handle and there is not a way to easily handle this on scanning the device. So polling should help make sure nothing // else goes on while write same is running. - TJE @@ -2602,7 +2910,7 @@ int32_t main(int argc, char *argv[]) } else { - writeSameRet = writesame(&deviceList[deviceIter], localStartLBA, localRange, true, NULL, 0); + writeSameRet = writesame(&deviceList[deviceIter], localStartLBA, localRange, true, M_NULLPTR, 0); } os_Unlock_Device(&deviceList[deviceIter]); //now we need to send the erase @@ -2611,7 +2919,7 @@ int32_t main(int argc, char *argv[]) case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully erased LBAs %"PRIu64" to %"PRIu64" using write same\n", localStartLBA, localStartLBA + localRange - 1); + printf("Successfully erased LBAs %" PRIu64 " to %" PRIu64 " using write same\n", localStartLBA, localStartLBA + localRange - 1); } eraseCompleted = true; break; @@ -2625,7 +2933,7 @@ int32_t main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to erase LBAs %"PRIu64" to %"PRIu64" with write same\n", localStartLBA, localStartLBA + localRange - 1); + printf("Failed to erase LBAs %" PRIu64 " to %" PRIu64 " with write same\n", localStartLBA, localStartLBA + localRange - 1); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -2689,7 +2997,7 @@ int32_t main(int argc, char *argv[]) case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully trimmed/unmapped LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Successfully trimmed/unmapped LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } eraseCompleted = true; break; @@ -2703,7 +3011,7 @@ int32_t main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to trim/unmap LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Failed to trim/unmap LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -2739,7 +3047,7 @@ int32_t main(int argc, char *argv[]) //determine if it's timed or a range if (overwriteSeconds == 0) { - int overwriteRet = UNKNOWN; + eReturnValues overwriteRet = UNKNOWN; uint64_t localStartLBA = OVERWRITE_START_FLAG; uint64_t localRange = OVERWRITE_RANGE_FLAG; if (USE_MAX_LBA) @@ -2773,7 +3081,7 @@ int32_t main(int argc, char *argv[]) } else { - overwriteRet = erase_Range(&deviceList[deviceIter], localStartLBA, localStartLBA + localRange, NULL, 0, HIDE_LBA_COUNTER); + overwriteRet = erase_Range(&deviceList[deviceIter], localStartLBA, localStartLBA + localRange, M_NULLPTR, 0, HIDE_LBA_COUNTER); } switch (overwriteRet) { @@ -2781,7 +3089,7 @@ int32_t main(int argc, char *argv[]) exitCode = 0; if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully overwrote LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Successfully overwrote LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } eraseCompleted = true; break; @@ -2795,7 +3103,7 @@ int32_t main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to erase LBAs %"PRIu64" to %"PRIu64"\n", localStartLBA, localStartLBA + localRange - 1); + printf("Failed to erase LBAs %" PRIu64 " to %" PRIu64 "\n", localStartLBA, localStartLBA + localRange - 1); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -2805,14 +3113,14 @@ int32_t main(int argc, char *argv[]) { if (overwriteSeconds > 0) { - int overwriteRet = UNKNOWN; + eReturnValues overwriteRet = UNKNOWN; if (PATTERN_FLAG) { overwriteRet = erase_Time(&deviceList[deviceIter], OVERWRITE_START_FLAG, overwriteSeconds, PATTERN_BUFFER, deviceList[deviceIter].drive_info.deviceBlockSize, HIDE_LBA_COUNTER); } else { - overwriteRet = erase_Time(&deviceList[deviceIter], OVERWRITE_START_FLAG, overwriteSeconds, NULL, 0, HIDE_LBA_COUNTER); + overwriteRet = erase_Time(&deviceList[deviceIter], OVERWRITE_START_FLAG, overwriteSeconds, M_NULLPTR, 0, HIDE_LBA_COUNTER); } switch (overwriteRet) { @@ -2861,9 +3169,9 @@ int32_t main(int argc, char *argv[]) } } - if (PROGRESS_CHAR != NULL) + if (PROGRESS_CHAR != M_NULLPTR) { - int result = UNKNOWN; + eReturnValues result = UNKNOWN; //first take whatever was entered in progressTest and convert it to uppercase to do fewer string comparisons convert_String_To_Upper_Case(progressTest); //do some string comparisons to figure out what we are checking for progress on @@ -2921,15 +3229,42 @@ int32_t main(int argc, char *argv[]) break; } } - if (eraseCompleted) + if (eraseCompleted || REFRESH_FILE_SYSTEMS) { //update the FS cache since just about all actions in here will need this if they do not already handle it internally. - os_Update_File_System_Cache(&deviceList[deviceIter]); + eReturnValues fsret = os_Update_File_System_Cache(&deviceList[deviceIter]); + if (REFRESH_FILE_SYSTEMS) + { + switch (fsret) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Successfully refreshed the filesystems for the OS!\n"); + } + eraseCompleted = true; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Refreshing the filesystems is not supported in this OS.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to refresh the OS file systems.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } } //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -2987,7 +3322,7 @@ void utility_Usage(bool shortUsage) printf("\nReturn codes\n"); printf("============\n"); int totalErrorCodes = SEACHEST_ERASE_EXIT_MAX_ERROR - SEACHEST_ERASE_EXIT_ZERO_VALIDATION_FAILURE; - ptrToolSpecificxitCode seachestEraseExitCodes = C_CAST(ptrToolSpecificxitCode, calloc(totalErrorCodes, sizeof(toolSpecificxitCode))); + ptrToolSpecificxitCode seachestEraseExitCodes = C_CAST(ptrToolSpecificxitCode, safe_calloc(int_to_sizet(totalErrorCodes), sizeof(toolSpecificxitCode))); //now set up all the exit codes and their meanings if (seachestEraseExitCodes) { @@ -2999,7 +3334,7 @@ void utility_Usage(bool shortUsage) case SEACHEST_ERASE_EXIT_ZERO_VALIDATION_FAILURE: snprintf(seachestEraseExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCodeString, TOOL_EXIT_CODE_STRING_MAX_LENGTH, "Zero Validation Failure"); break; - //TODO: add more exit codes here! + //add more exit codes here! default://We shouldn't ever hit the default case! break; } @@ -3052,15 +3387,16 @@ void utility_Usage(bool shortUsage) print_Fast_Discovery_Help(shortUsage); print_Time_Hours_Help(shortUsage); print_Time_Minutes_Help(shortUsage); - #if !defined(DISABLE_TCG_SUPPORT) +#if !defined(DISABLE_TCG_SUPPORT) print_TCG_PSID_Help(shortUsage); - #endif +#endif print_Time_Seconds_Help(shortUsage); print_Erase_Restore_Max_Prep_Help(shortUsage); + print_Refresh_Filesystems_Help(shortUsage); print_Show_Supported_Erase_Modes_Help(shortUsage); - #if !defined(DISABLE_TCG_SUPPORT) +#if !defined(DISABLE_TCG_SUPPORT) print_TCG_SID_Help(shortUsage); - #endif +#endif print_Zero_Verify_Help(shortUsage); //SATA Only Options @@ -3097,27 +3433,34 @@ void utility_Usage(bool shortUsage) printf("SATA - IO, and NVMexpress.\n"); printf("=========================\n"); //multiple interfaces + print_Sanitize_AUSE_Help(shortUsage); + print_Sanitize_Overwrite_Invert_Help(shortUsage); print_Overwrite_Help(shortUsage); print_Overwrite_Range_Help(shortUsage); + print_Sanitize_Overwrite_Passes_Help(shortUsage); print_Pattern_Help(shortUsage); print_Perform_Quickest_Erase_Help(shortUsage); - #if !defined(DISABLE_TCG_SUPPORT) +#if !defined(DISABLE_TCG_SUPPORT) print_Revert_Help(shortUsage); print_RevertSP_Help(shortUsage); - #endif +#endif print_Sanitize_Help(shortUsage, util_name); print_Trim_Unmap_Help(shortUsage); print_Trim_Unmap_Range_Help(shortUsage); print_Writesame_Help(shortUsage); print_Writesame_Range_Help(shortUsage); + print_Zone_No_Reset_Help(shortUsage); //SATA Only Options printf("\n\tSATA Only:\n\t=========\n"); print_ATA_Security_Erase_Help(shortUsage, "SeaChest"); + print_Sanitize_Anti_Freeze_Help(shortUsage); + print_Sanitize_Freeze_Help(shortUsage); //SAS Only Options printf("\n\tSAS Only:\n\t=========\n"); print_Fast_Format_Help(shortUsage); print_Format_Unit_Help(shortUsage); printf("\n\tNVMe Only:\n\t=========\n"); + print_Sanitize_No_Deallocate_Help(shortUsage); print_NVM_Format_Metadata_Setting_Help(shortUsage); print_NVM_Format_Metadata_Size_Help(shortUsage); print_NVM_Format_NSID_Help(shortUsage); diff --git a/utils/C/openSeaChest/openSeaChest_Firmware.c b/utils/C/openSeaChest/openSeaChest_Firmware.c index 83c18660..3d8b78a2 100644 --- a/utils/C/openSeaChest/openSeaChest_Firmware.c +++ b/utils/C/openSeaChest/openSeaChest_Firmware.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,8 +15,22 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "secure_file.h" +#include "precision_timer.h" +#include "sleep.h" +#include "math_utils.h" +#if defined (_WIN32) +#include "windows_version_detect.h" //for WinAPI checks and functions +#endif + +#include <time.h> +#include <stdbool.h> #if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition #include <unistd.h> #endif @@ -29,7 +44,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Firmware"; -const char *buildVersion = "4.0.0"; +const char *buildVersion = "4.2.0"; typedef enum _eSeaChestFirmwareExitCodes { @@ -64,14 +79,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char* argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -115,8 +130,9 @@ int32_t main(int argc, char *argv[]) CSMI_VERBOSE_VAR #endif LOWLEVEL_INFO_VAR + SHOW_SCSI_FW_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -203,10 +219,10 @@ int32_t main(int argc, char *argv[]) { case 0: //parse long options that have no short option and required arguments here - if (strncmp(longopts[optionIndex].name, DOWNLOAD_FW_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(DOWNLOAD_FW_LONG_OPT_STRING))) == 0) + if (strcmp(longopts[optionIndex].name, DOWNLOAD_FW_LONG_OPT_STRING) == 0) { - int scanRet = sscanf(optarg, FIRMWARE_FILE_NAME_MAX_LEN_FORMAT_STR, DOWNLOAD_FW_FILENAME_FLAG); - if (scanRet > 0 && scanRet != EOF) + int res = snprintf(DOWNLOAD_FW_FILENAME_FLAG, FIRMWARE_FILE_NAME_MAX_LEN, "%s", optarg); + if (res > 0 && res <= FIRMWARE_FILE_NAME_MAX_LEN) { DOWNLOAD_FW_FLAG = true; } @@ -216,7 +232,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, DOWNLOAD_FW_MODE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(DOWNLOAD_FW_MODE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, DOWNLOAD_FW_MODE_LONG_OPT_STRING) == 0) { DOWNLOAD_FW_MODE = FWDL_UPDATE_MODE_AUTOMATIC; if (strcmp(optarg, "immediate") == 0 || strcmp(optarg, "full") == 0) @@ -250,45 +266,51 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, NEW_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(NEW_FW_MATCH_LONG_OPT_STRING))) == 0) - { - NEW_FW_MATCH_FLAG = true; - snprintf(NEW_FW_STRING_FLAG, NEW_FW_MATCH_STRING_LENGTH, "%s", optarg); - } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_NEW_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_NEW_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, NEW_FW_MATCH_LONG_OPT_STRING) == 0) + { + NEW_FW_MATCH_FLAG = true; + snprintf(NEW_FW_STRING_FLAG, NEW_FW_MATCH_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, CHILD_NEW_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_NEW_FW_MATCH_FLAG = true; snprintf(CHILD_NEW_FW_STRING_FLAG, CHILD_NEW_FW_STRING_MATCH_LENGTH, "%s", optarg); } else if (strcmp(longopts[optionIndex].name, FWDL_SEGMENT_SIZE_LONG_OPT_STRING) == 0) { - FWDL_SEGMENT_SIZE_FROM_USER = true; - FWDL_SEGMENT_SIZE_FLAG = C_CAST(uint16_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FWDL_SEGMENT_SIZE_FLAG)) + { + FWDL_SEGMENT_SIZE_FROM_USER = true; + } + else + { + print_Error_In_Cmd_Line_Args(FWDL_SEGMENT_SIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, FIRMWARE_SLOT_LONG_OPT_STRING) == 0 || strcmp(longopts[optionIndex].name, FIRMWARE_BUFFER_ID_LONG_OPT_STRING) == 0) { - FIRMWARE_SLOT_FLAG = C_CAST(uint8_t, atoi(optarg)); - if (FIRMWARE_SLOT_FLAG > 7) + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FIRMWARE_SLOT_FLAG) || FIRMWARE_SLOT_FLAG > 7) { if (toolVerbosity > VERBOSITY_QUIET) { @@ -299,12 +321,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, FORCE_NVME_COMMIT_ACTION_LONG_OPT_STRING) == 0) { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(optarg, &temp)) - { - FORCE_NVME_COMMIT_ACTION = C_CAST(uint8_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FORCE_NVME_COMMIT_ACTION)) { print_Error_In_Cmd_Line_Args(FORCE_NVME_COMMIT_ACTION_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -374,9 +391,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -413,7 +431,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -444,11 +462,11 @@ int32_t main(int argc, char *argv[]) print_Elevated_Privileges_Text(); } unsigned int scanControl = DEFAULT_SCAN; - if(AGRESSIVE_SCAN_FLAG) + if (AGRESSIVE_SCAN_FLAG) { scanControl |= AGRESSIVE_SCAN; } - #if defined (__linux__) +#if defined (__linux__) if (SCAN_FLAGS.scanSD) { scanControl |= SD_HANDLES; @@ -457,7 +475,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SG_TO_SD; } - #endif +#endif //set the drive types to show (if none are set, the lower level code assumes we need to show everything) if (SCAN_FLAGS.scanATA) { @@ -510,7 +528,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -566,6 +584,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -600,7 +620,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -643,11 +663,12 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; } + ret = get_Device_List(DEVICE_LIST, DEVICE_LIST_COUNT * sizeof(tDevice), version, flags); if (SUCCESS != ret) { @@ -691,11 +712,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -713,38 +734,40 @@ int32_t main(int argc, char *argv[]) #if defined(_DEBUG) printf("Attempting to open handle \"%s\"\n", HANDLE_LIST[handleIter]); #endif - ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); + ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); #if !defined(_WIN32) #if !defined(VMK_CROSS_COMP) - if ((deviceList[handleIter].os_info.fd < 0) || + if ((deviceList[handleIter].os_info.fd < 0) || #else - if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + if (((deviceList[handleIter].os_info.fd < 0) && + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif - (ret == FAILURE || ret == PERMISSION_DENIED)) + (ret == FAILURE || ret == PERMISSION_DENIED)) #else - if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) + if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) #endif - { - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); - } - free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); - if(ret == PERMISSION_DENIED || !is_Running_Elevated()) - { - exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); - } - else { - exit(UTIL_EXIT_OPERATION_FAILURE); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } } - } + } } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); for (uint32_t deviceIter = 0; deviceIter < DEVICE_LIST_COUNT; ++deviceIter) { + deviceList[deviceIter].deviceVerbosity = toolVerbosity; if (ONLY_SEAGATE_FLAG) { @@ -761,7 +784,8 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -770,6 +794,7 @@ int32_t main(int argc, char *argv[]) continue; } } + //check for fw already loaded if (NEW_FW_MATCH_FLAG) { @@ -782,6 +807,7 @@ int32_t main(int argc, char *argv[]) continue; } } + //check for fw match if (FW_MATCH_FLAG) { @@ -798,7 +824,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -850,6 +876,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -951,6 +986,38 @@ int32_t main(int argc, char *argv[]) } } + if (SHOW_SCSI_FW_INFO_FLAG) + { + //these live under at least seadragon for now...-TJE + seagateSCSIFWNumbers fwNumbers; + memset(&fwNumbers, 0, sizeof(seagateSCSIFWNumbers)); + switch (get_Seagate_SCSI_Firmware_Numbers(&deviceList[deviceIter], &fwNumbers)) + { + case SUCCESS: + printf("\n===SCSI Firmware Numbers===\n"); + printf(" SCSI Firmware Release Number: %s\n", fwNumbers.scsiFirmwareReleaseNumber); + printf(" Servo Firmware Release Number: %s\n", fwNumbers.servoFirmwareReleaseNumber); + printf(" SAP Block Point Numbers: %s\n", fwNumbers.sapBlockPointNumbers); + printf(" Servo Firmware Release Date: %s\n", fwNumbers.servoFirmmwareReleaseDate); + printf(" Servo ROM Release Date: %s\n", fwNumbers.servoRomReleaseDate); + printf(" SAP Firmware Release Number: %s\n", fwNumbers.sapFirmwareReleaseNumber); + printf(" SAP Firmware Release Date: %s\n", fwNumbers.sapFirmwareReleaseDate); + printf(" SAP Firmware Release Year: %s\n", fwNumbers.sapFirmwareReleaseYear); + printf(" SAP Manufacturing Key: %s\n", fwNumbers.sapManufacturingKey); + printf(" Servo Firmware Product Family and Product Family Member IDs: %s\n", fwNumbers.servoFirmwareProductFamilyAndProductFamilyMemberIDs); + break; + case NOT_SUPPORTED: + printf("SCSI Firmware Numbers not supported by this device\n"); + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + printf("Failed to retrieve SCSI Firmware Numbers from this device\n"); + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + + #if defined (_WIN32) if (deviceList[deviceIter].drive_info.drive_type == NVME_DRIVE && (FORCE_NVME_COMMIT_ACTION != 0xFF || FORCE_DISABLE_NVME_FW_COMMIT_RESET)) { @@ -969,36 +1036,21 @@ int32_t main(int argc, char *argv[]) if (DOWNLOAD_FW_FLAG) { - FILE *firmwareFilePtr = NULL; - bool fileOpenedSuccessfully = true;//assume true in case of activate command - if (DOWNLOAD_FW_MODE != FWDL_UPDATE_MODE_ACTIVATE) - { - //open the file and send the download - if ((firmwareFilePtr = fopen(DOWNLOAD_FW_FILENAME_FLAG, "rb")) == NULL) - { - fileOpenedSuccessfully = false; - } - } - if (DOWNLOAD_FW_MODE == FWDL_UPDATE_MODE_ACTIVATE) - { - //this shouldn't fall into this code path anymore... - fileOpenedSuccessfully = false; - } - if (fileOpenedSuccessfully) + secureFileInfo* fwfile = secure_Open_File(DOWNLOAD_FW_FILENAME_FLAG, "rb", M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (fwfile && fwfile->error == SEC_FILE_SUCCESS) { - size_t firmwareFileSize = get_File_Size(firmwareFilePtr); - uint8_t *firmwareMem = C_CAST(uint8_t*, calloc_aligned(firmwareFileSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t* firmwareMem = C_CAST(uint8_t*, safe_calloc_aligned(fwfile->fileSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (firmwareMem) { - if(firmwareFileSize == fread(firmwareMem, sizeof(uint8_t), firmwareFileSize, firmwareFilePtr)) - { + if (SEC_FILE_SUCCESS == secure_Read_File(fwfile, firmwareMem, fwfile->fileSize, sizeof(uint8_t), fwfile->fileSize, M_NULLPTR)) + { firmwareUpdateData dlOptions; seatimer_t commandTimer; memset(&dlOptions, 0, sizeof(firmwareUpdateData)); memset(&commandTimer, 0, sizeof(seatimer_t)); dlOptions.size = sizeof(firmwareUpdateData); dlOptions.version = FIRMWARE_UPDATE_DATA_VERSION; - dlOptions.dlMode = DOWNLOAD_FW_MODE; + dlOptions.dlMode = C_CAST(eFirmwareUpdateMode, DOWNLOAD_FW_MODE); if (FWDL_SEGMENT_SIZE_FROM_USER) { dlOptions.segmentSize = FWDL_SEGMENT_SIZE_FLAG; @@ -1009,7 +1061,7 @@ int32_t main(int argc, char *argv[]) } dlOptions.ignoreStatusOfFinalSegment = M_ToBool(FWDL_IGNORE_FINAL_SEGMENT_STATUS_FLAG); dlOptions.firmwareFileMem = firmwareMem; - dlOptions.firmwareMemoryLength = C_CAST(uint32_t, firmwareFileSize);//firmware files shouldn't be larger than a few MBs for a LONG time + dlOptions.firmwareMemoryLength = C_CAST(uint32_t, fwfile->fileSize);//firmware files shouldn't be larger than a few MBs for a LONG time dlOptions.firmwareSlot = FIRMWARE_SLOT_FLAG; if (FORCE_NVME_COMMIT_ACTION != 0xFF) { @@ -1111,11 +1163,19 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(firmwareMem) + safe_free_aligned(&firmwareMem); } else { perror("failed to allocate memory"); + if (fwfile) + { + if (SEC_FILE_SUCCESS != secure_Close_File(fwfile)) + { + printf("Error attempting to close file!\n"); + } + free_Secure_File_Info(&fwfile); + } exit(255); } } @@ -1123,11 +1183,18 @@ int32_t main(int argc, char *argv[]) { if (VERBOSITY_QUIET < toolVerbosity) { - perror("fopen"); printf("Couldn't open file %s\n", DOWNLOAD_FW_FILENAME_FLAG); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + if (fwfile) + { + if (SEC_FILE_SUCCESS != secure_Close_File(fwfile)) + { + printf("Error attempting to close file!\n"); + } + free_Secure_File_Info(&fwfile); + } } if (ACTIVATE_DEFERRED_FW_FLAG || SWITCH_FW_FLAG) @@ -1147,7 +1214,7 @@ int32_t main(int argc, char *argv[]) dlOptions.version = FIRMWARE_UPDATE_DATA_VERSION; dlOptions.dlMode = FWDL_UPDATE_MODE_ACTIVATE; dlOptions.segmentSize = 0; - dlOptions.firmwareFileMem = NULL; + dlOptions.firmwareFileMem = M_NULLPTR; dlOptions.firmwareMemoryLength = 0; dlOptions.firmwareSlot = FIRMWARE_SLOT_FLAG; if (SWITCH_FW_FLAG) @@ -1247,7 +1314,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1292,7 +1359,7 @@ void utility_Usage(bool shortUsage) printf("============\n"); //SEACHEST_FIRMWARE_EXIT_MAX_ERROR - SEACHEST_FIRMWARE_EXIT_FIRMWARE_DOWNLOAD_COMPLETE int totalErrorCodes = SEACHEST_FIRMWARE_EXIT_MAX_ERROR - SEACHEST_FIRMWARE_EXIT_FIRMWARE_DOWNLOAD_COMPLETE; - ptrToolSpecificxitCode seachestFirmwareExitCodes = C_CAST(ptrToolSpecificxitCode, calloc(totalErrorCodes, sizeof(toolSpecificxitCode))); + ptrToolSpecificxitCode seachestFirmwareExitCodes = C_CAST(ptrToolSpecificxitCode, safe_calloc(int_to_sizet(totalErrorCodes), sizeof(toolSpecificxitCode))); //now set up all the exit codes and their meanings if (seachestFirmwareExitCodes) { @@ -1328,7 +1395,7 @@ void utility_Usage(bool shortUsage) case SEACHEST_FIRMWARE_EXIT_MATCH_FOUND_DEFERRED_SUPPORTED: snprintf(seachestFirmwareExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCodeString, TOOL_EXIT_CODE_STRING_MAX_LENGTH, "Firmware Match Found for update - deferred update supported"); break; - //TODO: add more exit codes here! + //add more exit codes here! default://We shouldn't ever hit the default case! break; } diff --git a/utils/C/openSeaChest/openSeaChest_Format.c b/utils/C/openSeaChest/openSeaChest_Format.c index 521e9be8..aabd47be 100644 --- a/utils/C/openSeaChest/openSeaChest_Format.c +++ b/utils/C/openSeaChest/openSeaChest_Format.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,12 +15,16 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include "common_platform.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "secure_file.h" +#include "pattern_utils.h" +#include "sleep.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -32,7 +37,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Format"; -const char *buildVersion = "3.0.4"; +const char *buildVersion = "3.2.0"; //////////////////////////// // functions to declare // @@ -52,14 +57,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -85,7 +90,6 @@ int32_t main(int argc, char *argv[]) FORCE_VAR //scan output flags SCAN_FLAGS_UTIL_VARS - FORMAT_UNIT_VARS FAST_FORMAT_VAR FORMAT_UNIT_OPTION_FLAGS @@ -101,17 +105,15 @@ int32_t main(int argc, char *argv[]) REMOVE_PHYSICAL_ELEMENT_VAR REPOPULATE_ELEMENTS_VAR DEPOP_MAX_LBA_VAR - NVM_FORMAT_VARS NVM_FORMAT_OPTION_VARS - #if defined (ENABLE_CSMI) CSMI_FORCE_VARS CSMI_VERBOSE_VAR #endif LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -164,6 +166,7 @@ int32_t main(int argc, char *argv[]) DEPOP_MAX_LBA_LONG_OPT, NVM_FORMAT_LONG_OPT, NVM_FORMAT_OPTIONS_LONG_OPTS, + FORCE_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -220,22 +223,22 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -245,26 +248,18 @@ int32_t main(int argc, char *argv[]) FORMAT_UNIT_FLAG = true; if (strcmp(optarg, "current") != 0) { - uint64_t tempSectorSize = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &tempSectorSize)) - { - //set the sector size - FORMAT_SECTOR_SIZE = C_CAST(uint16_t, tempSectorSize); - } - else + if (!get_And_Validate_Integer_Input_Uint16(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &FORMAT_SECTOR_SIZE)) { print_Error_In_Cmd_Line_Args(FORMAT_UNIT_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } } - else if (strncmp(longopts[optionIndex].name, SET_SECTOR_SIZE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_SECTOR_SIZE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_SECTOR_SIZE_LONG_OPT_STRING) == 0) { - uint64_t tempSectorSize = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &tempSectorSize)) + if (get_And_Validate_Integer_Input_Uint32(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &SET_SECTOR_SIZE_SIZE)) { SET_SECTOR_SIZE_FLAG = true; - SET_SECTOR_SIZE_SIZE = C_CAST(uint32_t, tempSectorSize); } else { @@ -274,7 +269,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, DISPLAY_LBA_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &DISPLAY_LBA_THE_LBA)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &DISPLAY_LBA_THE_LBA)) { DISPLAY_LBA_FLAG = true; } @@ -299,21 +294,39 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, FAST_FORMAT_LONG_OPT_STRING) == 0) { - FAST_FORMAT_FLAG = C_CAST(eFormatType, atoi(optarg)); + if (!get_And_Validate_Integer_Input_I(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FAST_FORMAT_FLAG)) + { + print_Error_In_Cmd_Line_Args(FAST_FORMAT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT_STRING) == 0) { - FORMAT_UNIT_PROTECTION_TYPE = C_CAST(uint8_t, atoi(optarg)); - FORMAT_UNIT_PROECTION_TYPE_FROM_USER = true; + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FORMAT_UNIT_PROTECTION_TYPE)) + { + FORMAT_UNIT_PROECTION_TYPE_FROM_USER = true; + } + else + { + print_Error_In_Cmd_Line_Args(FORMAT_UNIT_PROTECTION_TYPE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT_STRING) == 0) { - FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT = C_CAST(uint8_t, atoi(optarg)); - FORMAT_UNIT_PROECTION_INTERVAL_EXPONENT_FROM_USER = true; + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT)) + { + FORMAT_UNIT_PROECTION_INTERVAL_EXPONENT_FROM_USER = true; + } + else + { + print_Error_In_Cmd_Line_Args(FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &FORMAT_UNIT_NEW_MAX_LBA)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &FORMAT_UNIT_NEW_MAX_LBA)) { print_Error_In_Cmd_Line_Args(FORMAT_UNIT_NEW_MAX_LBA_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -321,7 +334,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, DEPOP_MAX_LBA_LONG_OPT_STRING) == 0) { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &DEPOP_MAX_LBA_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &DEPOP_MAX_LBA_FLAG)) { print_Error_In_Cmd_Line_Args(DEPOP_MAX_LBA_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -329,12 +342,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, REMOVE_PHYSICAL_ELEMENT_LONG_OPT_STRING) == 0)//REMOVE_PHYSICAL_ELEMENT_LONG_OPT_STRING { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &temp)) - { - REMOVE_PHYSICAL_ELEMENT_FLAG = C_CAST(uint32_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Uint32(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &REMOVE_PHYSICAL_ELEMENT_FLAG)) { print_Error_In_Cmd_Line_Args(REMOVE_PHYSICAL_ELEMENT_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -345,12 +353,7 @@ int32_t main(int argc, char *argv[]) NVM_FORMAT_FLAG = true; if (strcmp(optarg, "current") != 0) { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &temp)) - { - NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM = C_CAST(uint32_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Uint32(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM)) { print_Error_In_Cmd_Line_Args(NVM_FORMAT_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -395,7 +398,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_PI_TYPE_LONG_OPT_STRING) == 0) { - NVM_FORMAT_PI_TYPE = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_PI_TYPE) || NVM_FORMAT_PI_TYPE > 3) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_PI_TYPE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_PI_LOCATION_LONG_OPT_STRING) == 0) { @@ -415,7 +422,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING) == 0) { - NVM_FORMAT_METADATA_SIZE = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_METADATA_SIZE)) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_METADATA_SETTING_LONG_OPT_STRING) == 0) { @@ -448,49 +459,78 @@ int32_t main(int argc, char *argv[]) colonLocation += 1;//adding 1 to offset just beyond the colon for parsing the remaining data if (strncmp("file:", optarg, 5) == 0) { - FILE *patternFile = NULL; - size_t filenameLength = strlen(colonLocation) + 1; - char *filename = C_CAST(char*, calloc(filenameLength, sizeof(char))); - if (!filename) + fileExt allowedExt[] = { + {".bin", false}, + {".BIN", false}, + {M_NULLPTR, false} }; + secureFileInfo* fileinfo = secure_Open_File(colonLocation, "rb", allowedExt, M_NULLPTR, M_NULLPTR); + if (fileinfo) { - exit(UTIL_EXIT_CANNOT_OPEN_FILE); + if (fileinfo->error == SEC_FILE_SUCCESS) + { + if (SEC_FILE_SUCCESS != secure_Read_File(fileinfo, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH, sizeof(uint8_t), fileinfo->fileSize, M_NULLPTR)) + { + if (fileinfo->error == SEC_FILE_END_OF_FILE_REACHED) + { + } + else + { + printf("Unable to read contents of the file \"%s\" for the pattern.\n", fileinfo->filename); + if (SEC_FILE_SUCCESS != secure_Close_File(fileinfo)) + { + printf("secure file structure could not be closed! This is a fatal error!\n"); + } + free_Secure_File_Info(&fileinfo); + exit(UTIL_EXIT_CANNOT_OPEN_FILE); + } + } + } + else + { + printf("Unable to open file \"%s\" for pattern\n", colonLocation); + exit(UTIL_EXIT_CANNOT_OPEN_FILE); + } + if (SEC_FILE_SUCCESS == secure_Close_File(fileinfo)) + { + free_Secure_File_Info(&fileinfo); + } + else + { + printf("secure file structure could not be closed! This is a fatal error!\n"); + } } - snprintf(filename, filenameLength, "%s", colonLocation); - //open file - if (NULL == (patternFile = fopen(filename, "rb"))) - { - printf("Unable to open file \"%s\" for pattern\n", filename); - exit(UTIL_EXIT_CANNOT_OPEN_FILE); - } - //read contents into buffer - if (0 == fread(PATTERN_BUFFER, sizeof(uint8_t), M_Min(PATTERN_BUFFER_LENGTH, get_File_Size(patternFile)), patternFile)) + else { - printf("Unable to read contents of the file \"%s\" for the pattern.\n", filename); - fclose(patternFile); + printf("Unable to open file \"%s\" for pattern\n", colonLocation); exit(UTIL_EXIT_CANNOT_OPEN_FILE); } - //close file - fclose(patternFile); - safe_Free(filename); } else if (strncmp("increment:", optarg, 10) == 0) { - uint8_t incrementStart = C_CAST(uint8_t, atoi(colonLocation)); - fill_Incrementing_Pattern_In_Buffer(incrementStart, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); + uint8_t incrementStart = 0; + if (get_And_Validate_Integer_Input_Uint8(colonLocation, M_NULLPTR, ALLOW_UNIT_NONE, &incrementStart)) + { + fill_Incrementing_Pattern_In_Buffer(incrementStart, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); + } + else + { + print_Error_In_Cmd_Line_Args(PATTERN_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strncmp("repeat:", optarg, 7) == 0) { //if final character is a lower case h, it's an hex pattern - if (colonLocation[strlen(colonLocation) - 1] == 'h' && strlen(colonLocation) == 9) + if (colonLocation[safe_strlen(colonLocation) - 1] == 'h' && safe_strlen(colonLocation) == 9) { - uint32_t hexPattern = C_CAST(uint32_t, strtoul(colonLocation, NULL, 16)); + uint32_t hexPattern = C_CAST(uint32_t, strtoul(colonLocation, M_NULLPTR, 16)); //TODO: add endianness check before byte swap byte_Swap_32(&hexPattern); fill_Hex_Pattern_In_Buffer(hexPattern, PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); } else { - fill_ASCII_Pattern_In_Buffer(colonLocation, C_CAST(uint32_t, strlen(colonLocation)), PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); + fill_ASCII_Pattern_In_Buffer(colonLocation, C_CAST(uint32_t, safe_strlen(colonLocation)), PATTERN_BUFFER, PATTERN_BUFFER_LENGTH); } } else @@ -570,9 +610,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case PROGRESS_SHORT_OPT: //get test progress for a specific test @@ -612,7 +653,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -643,7 +684,7 @@ int32_t main(int argc, char *argv[]) print_Elevated_Privileges_Text(); } unsigned int scanControl = DEFAULT_SCAN; - if(AGRESSIVE_SCAN_FLAG) + if (AGRESSIVE_SCAN_FLAG) { scanControl |= AGRESSIVE_SCAN; } @@ -709,7 +750,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -765,6 +806,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -788,7 +831,7 @@ int32_t main(int argc, char *argv[]) //check for other tool specific options here || FORMAT_UNIT_FLAG || DISPLAY_LBA_FLAG - || (PROGRESS_CHAR != NULL) + || (PROGRESS_CHAR != M_NULLPTR) || SHOW_FORMAT_STATUS_LOG_FLAG || SET_SECTOR_SIZE_FLAG || SHOW_SUPPORTED_FORMATS_FLAG @@ -804,7 +847,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -847,7 +890,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -895,11 +938,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -917,33 +960,34 @@ int32_t main(int argc, char *argv[]) #if defined(_DEBUG) printf("Attempting to open handle \"%s\"\n", HANDLE_LIST[handleIter]); #endif - ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); + ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); #if !defined(_WIN32) #if !defined(VMK_CROSS_COMP) - if ((deviceList[handleIter].os_info.fd < 0) || + if ((deviceList[handleIter].os_info.fd < 0) || #else - if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + if (((deviceList[handleIter].os_info.fd < 0) && + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif - (ret == FAILURE || ret == PERMISSION_DENIED)) + (ret == FAILURE || ret == PERMISSION_DENIED)) #else - if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) + if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) #endif - { - if (VERBOSITY_QUIET < toolVerbosity) - { - printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); - } - free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); - if(ret == PERMISSION_DENIED || !is_Running_Elevated()) - { - exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); - } - else { - exit(UTIL_EXIT_OPERATION_FAILURE); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } } - } + } } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); @@ -1017,7 +1061,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1042,7 +1086,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1082,6 +1126,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1144,7 +1197,7 @@ int32_t main(int argc, char *argv[]) if (DISPLAY_LBA_FLAG) { - uint8_t *displaySector = C_CAST(uint8_t*, calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t *displaySector = C_CAST(uint8_t*, safe_calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (!displaySector) { perror("Could not allocate memory to read LBA."); @@ -1160,22 +1213,22 @@ int32_t main(int argc, char *argv[]) } if (SUCCESS == read_LBA(&deviceList[deviceIter], DISPLAY_LBA_THE_LBA, false, displaySector, deviceList[deviceIter].drive_info.deviceBlockSize)) { - printf("\nContents of LBA %"PRIu64":\n", DISPLAY_LBA_THE_LBA); + printf("\nContents of LBA %" PRIu64 ":\n", DISPLAY_LBA_THE_LBA); print_Data_Buffer(displaySector, deviceList[deviceIter].drive_info.deviceBlockSize, true); } else { - printf("Error Reading LBA %"PRIu64" for display\n", DISPLAY_LBA_THE_LBA); + printf("Error Reading LBA %" PRIu64 " for display\n", DISPLAY_LBA_THE_LBA); exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(displaySector) + safe_free_aligned(&displaySector); } if (SHOW_SUPPORTED_FORMATS_FLAG) { uint32_t numberOfSectorSizes = get_Number_Of_Supported_Sector_Sizes(&deviceList[deviceIter]); uint32_t memSize = sizeof(supportedFormats) + sizeof(sectorSize) * numberOfSectorSizes; - ptrSupportedFormats formats = C_CAST(ptrSupportedFormats, malloc(memSize)); + ptrSupportedFormats formats = C_CAST(ptrSupportedFormats, safe_malloc(memSize)); if (VERBOSITY_QUIET < toolVerbosity) { @@ -1207,7 +1260,7 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; break; } - safe_Free(formats); + safe_free_supported_formats(&formats); } else { @@ -1256,7 +1309,7 @@ int32_t main(int argc, char *argv[]) get_Number_Of_Descriptors(&deviceList[deviceIter], &numberOfDescriptors); if (numberOfDescriptors > 0) { - ptrPhysicalElement elementList = C_CAST(ptrPhysicalElement, malloc(numberOfDescriptors * sizeof(physicalElement))); + ptrPhysicalElement elementList = C_CAST(ptrPhysicalElement, safe_malloc(numberOfDescriptors * sizeof(physicalElement))); memset(elementList, 0, numberOfDescriptors * sizeof(physicalElement)); if (SUCCESS == get_Physical_Element_Descriptors(&deviceList[deviceIter], numberOfDescriptors, elementList)) { @@ -1305,11 +1358,11 @@ int32_t main(int argc, char *argv[]) { currentBlockSize = false; } - formatUnitParameters.formatType = FAST_FORMAT_FLAG; + formatUnitParameters.formatType = C_CAST(eFormatType, FAST_FORMAT_FLAG); formatUnitParameters.currentBlockSize = currentBlockSize; formatUnitParameters.newBlockSize = FORMAT_SECTOR_SIZE; formatUnitParameters.newMaxLBA = FORMAT_UNIT_NEW_MAX_LBA;//if zero, this is ignored - formatUnitParameters.gList = NULL; + formatUnitParameters.gList = M_NULLPTR; formatUnitParameters.glistSize = 0; formatUnitParameters.completeList = FORMAT_UNIT_DISCARD_GROWN_DEFECT_LIST_FLAG; formatUnitParameters.defaultFormat = true;//Setting this to ture as the default UNLESS one of the format option flags is given!!! - TJE @@ -1351,7 +1404,7 @@ int32_t main(int argc, char *argv[]) formatUnitParameters.protectionIntervalExponent = FORMAT_UNIT_PROTECTION_INTERVAL_EXPONENT; } formatUnitParameters.securityInitialize = false; - int formatRet = run_Format_Unit(&deviceList[deviceIter], formatUnitParameters, POLL_FLAG); + eReturnValues formatRet = run_Format_Unit(&deviceList[deviceIter], formatUnitParameters, POLL_FLAG); switch (formatRet) { case SUCCESS: @@ -1456,7 +1509,7 @@ int32_t main(int argc, char *argv[]) { printf("Set Sector Size to %" PRIu32 "\n", SET_SECTOR_SIZE_SIZE); } - switch (set_Sector_Configuration(&deviceList[deviceIter], SET_SECTOR_SIZE_SIZE)) + switch (set_Sector_Configuration_With_Force(&deviceList[deviceIter], SET_SECTOR_SIZE_SIZE, FORCE_FLAG)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1553,10 +1606,9 @@ int32_t main(int argc, char *argv[]) { if (LOW_LEVEL_FORMAT_FLAG) { - bool depopSupport = is_Depopulation_Feature_Supported(&deviceList[deviceIter], NULL); + bool depopSupport = is_Depopulation_Feature_Supported(&deviceList[deviceIter], M_NULLPTR); if (depopSupport) { - //TODO: add an option to allow setting a requested MaxLBA? Lets wait to see if a customer wants that option before we add it - TJE switch (perform_Depopulate_Physical_Element(&deviceList[deviceIter], REMOVE_PHYSICAL_ELEMENT_FLAG, DEPOP_MAX_LBA_FLAG, POLL_FLAG)) { case SUCCESS: @@ -1595,7 +1647,7 @@ int32_t main(int argc, char *argv[]) default: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Failed to depopulate element %" PRIu32".\n", REMOVE_PHYSICAL_ELEMENT_FLAG); + printf("Failed to depopulate element %" PRIu32 ".\n", REMOVE_PHYSICAL_ELEMENT_FLAG); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -1627,7 +1679,7 @@ int32_t main(int argc, char *argv[]) { if (LOW_LEVEL_FORMAT_FLAG) { - bool repopSupport = is_Repopulate_Feature_Supported(&deviceList[deviceIter], NULL); + bool repopSupport = is_Repopulate_Feature_Supported(&deviceList[deviceIter], M_NULLPTR); if (repopSupport) { switch (perform_Repopulate_Physical_Element(&deviceList[deviceIter], POLL_FLAG)) @@ -1641,7 +1693,7 @@ int32_t main(int argc, char *argv[]) } else { - printf("Successfully started repopulation.\n"); + printf("Successfully started repopulation.\n"); printf("The device may take a long time before it is ready to accept all commands again.\n"); printf("Use \"--%s repop\" or \"--%s\" to check progress.\n", PROGRESS_LONG_OPT_STRING, SHOW_PHYSICAL_ELEMENT_STATUS_LONG_OPT_STRING); } @@ -1773,7 +1825,7 @@ int32_t main(int argc, char *argv[]) default: break; } - int formatRet = run_NVMe_Format(&deviceList[deviceIter], nvmformatParameters, POLL_FLAG); + eReturnValues formatRet = run_NVMe_Format(&deviceList[deviceIter], nvmformatParameters, POLL_FLAG); switch (formatRet) { case SUCCESS: @@ -1832,9 +1884,9 @@ int32_t main(int argc, char *argv[]) } } - if (PROGRESS_CHAR != NULL) + if (PROGRESS_CHAR != M_NULLPTR) { - int result = UNKNOWN; + eReturnValues result = UNKNOWN; //first take whatever was entered in progressTest and convert it to uppercase to do fewer string comparisons convert_String_To_Upper_Case(progressTest); //do some string comparisons to figure out what we are checking for progress on @@ -1891,7 +1943,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1937,11 +1989,11 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s current --%s --%s user\n", util_name, deviceHandleExample, NVM_FORMAT_LONG_OPT_STRING, POLL_LONG_OPT_STRING, NVM_FORMAT_SECURE_ERASE_LONG_OPT_STRING); printf("\t%s -d %s --%s current --%s --%s 1\n", util_name, deviceHandleExample, NVM_FORMAT_LONG_OPT_STRING, POLL_LONG_OPT_STRING, NVM_FORMAT_PI_TYPE_LONG_OPT_STRING); //TODO: Format and NVM format with PI - + //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); diff --git a/utils/C/openSeaChest/openSeaChest_GenericTests.c b/utils/C/openSeaChest/openSeaChest_GenericTests.c index f3e5bd2f..68551ee4 100644 --- a/utils/C/openSeaChest/openSeaChest_GenericTests.c +++ b/utils/C/openSeaChest/openSeaChest_GenericTests.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,15 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "time_utils.h" +#include "math_utils.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -30,7 +35,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_GenericTests"; -const char *buildVersion = "2.2.2"; +const char *buildVersion = "2.3.0"; //////////////////////////// // functions to declare // @@ -50,14 +55,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -205,14 +210,14 @@ int32_t main(int argc, char *argv[]) //parse long options that have no short option and required arguments here if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { - if (strlen(optarg) == strlen(DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, DATA_ERASE_ACCEPT_STRING, strlen(DATA_ERASE_ACCEPT_STRING)) == 0) + if (safe_strlen(optarg) == safe_strlen(DATA_ERASE_ACCEPT_STRING) && strcmp(optarg, DATA_ERASE_ACCEPT_STRING) == 0) { DATA_ERASE_FLAG = true; } } - else if (strncmp(longopts[optionIndex].name, USER_GENERIC_LONG_OPT_START_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(USER_GENERIC_LONG_OPT_START_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, USER_GENERIC_LONG_OPT_START_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &USER_GENERIC_START_FLAG)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &USER_GENERIC_START_FLAG)) { RUN_USER_GENERIC_TEST = true; } @@ -235,84 +240,136 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, USER_GENERIC_LONG_OPT_RANGE_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(USER_GENERIC_LONG_OPT_RANGE_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, USER_GENERIC_LONG_OPT_RANGE_STRING) == 0) { - USER_GENERIC_RANGE_FLAG = C_CAST(uint64_t, atoll(optarg)); - //Check to see if any units were specified, otherwise assume LBAs - uint64_t multiplier = 1; - if (strstr(optarg, "KB")) - { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000); - } - else if (strstr(optarg, "KiB")) + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint64(optarg, &unit, ALLOW_UNIT_DATASIZE, &USER_GENERIC_RANGE_FLAG)) { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1024); - } - else if (strstr(optarg, "MB")) - { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000000); - } - else if (strstr(optarg, "MiB")) - { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1048576); - } - else if (strstr(optarg, "GB")) - { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000000000); + //Check to see if any units were specified, otherwise assume LBAs + uint64_t multiplier = 1; + if (unit) + { + if (strcmp(unit, "") == 0) + { + multiplier = 1;//no additional units provided, so do not treat as an error + } + else if (strcmp(unit, "KB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000); + } + else if (strcmp(unit, "KiB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1024); + } + else if (strcmp(unit, "MB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000000); + } + else if (strcmp(unit, "MiB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1048576); + } + else if (strcmp(unit, "GB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000000000); + } + else if (strcmp(unit, "GiB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1073741824); + } + else if (strcmp(unit, "TB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000000000000); + } + else if (strcmp(unit, "TiB") == 0) + { + USER_GENERIC_RANGE_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1099511627776); + } + else + { + print_Error_In_Cmd_Line_Args(USER_GENERIC_LONG_OPT_RANGE_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + USER_GENERIC_RANGE_FLAG *= multiplier; } - else if (strstr(optarg, "GiB")) + else { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1073741824); + print_Error_In_Cmd_Line_Args(USER_GENERIC_LONG_OPT_RANGE_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - else if (strstr(optarg, "TB")) + } + else if (strcmp(longopts[optionIndex].name, ERROR_LIMIT_LONG_OPT_STRING) == 0) + { + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint16(optarg, &unit, ALLOW_UNIT_SECTOR_TYPE, &ERROR_LIMIT_FLAG)) { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000000000000); + if (unit) + { + if (strcmp(unit, "l") == 0) + { + ERROR_LIMIT_LOGICAL_COUNT = true; + } + else if (strcmp(unit, "p") == 0) + { + ERROR_LIMIT_LOGICAL_COUNT = false; + } + else + { + print_Error_In_Cmd_Line_Args(ERROR_LIMIT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } } - else if (strstr(optarg, "TiB")) + else { - USER_GENERIC_RANGE_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1099511627776); + print_Error_In_Cmd_Line_Args(ERROR_LIMIT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - USER_GENERIC_RANGE_FLAG *= multiplier;//Later we need to adjust this by the logical sector size...currently this is a value in bytes } - else if (strncmp(longopts[optionIndex].name, ERROR_LIMIT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ERROR_LIMIT_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, HOURS_TIME_LONG_OPT_STRING) == 0) { - ERROR_LIMIT_FLAG = C_CAST(uint16_t, atoi(optarg)); - if(strstr(optarg, "l")) + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &HOURS_TIME_FLAG)) { - ERROR_LIMIT_LOGICAL_COUNT = true; + print_Error_In_Cmd_Line_Args(HOURS_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, HOURS_TIME_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(HOURS_TIME_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MINUTES_TIME_LONG_OPT_STRING) == 0) { - HOURS_TIME_FLAG = C_CAST(uint8_t, atoi(optarg)); - } - else if (strncmp(longopts[optionIndex].name, MINUTES_TIME_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MINUTES_TIME_LONG_OPT_STRING))) == 0) - { - MINUTES_TIME_FLAG = C_CAST(uint16_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &MINUTES_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(MINUTES_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp(longopts[optionIndex].name, SECONDS_TIME_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SECONDS_TIME_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SECONDS_TIME_LONG_OPT_STRING) == 0) { - SECONDS_TIME_FLAG = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SECONDS_TIME_FLAG)) + { + print_Error_In_Cmd_Line_Args(SECONDS_TIME_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } - else if (strncmp(longopts[optionIndex].name, GENERIC_TEST_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(GENERIC_TEST_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, GENERIC_TEST_LONG_OPT_STRING) == 0) { - if (strncmp(optarg, "read", M_Min(4, strlen(optarg))) == 0) + if (strcmp(optarg, "read") == 0) { GENERIC_TEST_MODE_FLAG = RWV_COMMAND_READ; } - else if (strncmp(optarg, "write", M_Min(5, strlen(optarg))) == 0) + else if (strcmp(optarg, "write") == 0) { GENERIC_TEST_MODE_FLAG = RWV_COMMAND_WRITE; } - else if (strncmp(optarg, "verify", M_Min(6, strlen(optarg))) == 0) + else if (strcmp(optarg, "verify") == 0) { GENERIC_TEST_MODE_FLAG = RWV_COMMAND_VERIFY; } @@ -322,29 +379,29 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); } else if (strcmp(longopts[optionIndex].name, DISPLAY_LBA_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &DISPLAY_LBA_THE_LBA)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &DISPLAY_LBA_THE_LBA)) { DISPLAY_LBA_FLAG = true; } @@ -384,50 +441,70 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, OD_MD_ID_TEST_RANGE_LONG_OPT_STRING) == 0) { - OD_ID_MD_TEST_RANGE = C_CAST(uint64_t, atoll(optarg)); - //Check to see if any units were specified, otherwise assume LBAs - uint64_t multiplier = 1; - if (strstr(optarg, "KB")) - { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000); - } - else if (strstr(optarg, "KiB")) - { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1024); - } - else if (strstr(optarg, "MB")) - { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000000); - } - else if (strstr(optarg, "MiB")) - { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1048576); - } - else if (strstr(optarg, "GB")) + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint64(optarg, &unit, ALLOW_UNIT_DATASIZE, &OD_ID_MD_TEST_RANGE)) { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000000000); - } - else if (strstr(optarg, "GiB")) - { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1073741824); - } - else if (strstr(optarg, "TB")) - { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1000000000000); + //Check to see if any units were specified, otherwise assume LBAs + uint64_t multiplier = 1; + if (unit) + { + if (strcmp(unit, "") == 0) + { + multiplier = 1;//no additional units provided, so do not treat as an error + } + else if (strcmp(unit, "KB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000); + } + else if (strcmp(unit, "KiB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1024); + } + else if (strcmp(unit, "MB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000000); + } + else if (strcmp(unit, "MiB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1048576); + } + else if (strcmp(unit, "GB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000000000); + } + else if (strcmp(unit, "GiB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1073741824); + } + else if (strcmp(unit, "TB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1000000000000); + } + else if (strcmp(unit, "TiB") == 0) + { + OD_MD_ID_TEST_UNITS_SPECIFIED = true; + multiplier = UINT64_C(1099511627776); + } + else + { + print_Error_In_Cmd_Line_Args(OD_MD_ID_TEST_RANGE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + OD_ID_MD_TEST_RANGE *= multiplier; } - else if (strstr(optarg, "TiB")) + else { - OD_MD_ID_TEST_UNITS_SPECIFIED = true; - multiplier = UINT64_C(1099511627776); + print_Error_In_Cmd_Line_Args(OD_MD_ID_TEST_RANGE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - OD_ID_MD_TEST_RANGE *= multiplier;//Later we need to adjust this by the logical sector size...currently this is a value in bytes } break; case ':'://missing required argument @@ -493,9 +570,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -532,7 +610,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -629,7 +707,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -685,6 +763,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -723,7 +803,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -766,7 +846,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -814,11 +894,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -842,7 +922,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -884,7 +964,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -909,7 +989,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -949,6 +1029,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1020,7 +1109,7 @@ int32_t main(int argc, char *argv[]) if (DISPLAY_LBA_FLAG) { - uint8_t *displaySector = C_CAST(uint8_t*, calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t *displaySector = C_CAST(uint8_t*, safe_calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (!displaySector) { perror("Could not allocate memory to read LBA."); @@ -1036,15 +1125,15 @@ int32_t main(int argc, char *argv[]) } if (SUCCESS == read_LBA(&deviceList[deviceIter], DISPLAY_LBA_THE_LBA, false, displaySector, deviceList[deviceIter].drive_info.deviceBlockSize)) { - printf("\nContents of LBA %"PRIu64":\n", DISPLAY_LBA_THE_LBA); + printf("\nContents of LBA %" PRIu64 ":\n", DISPLAY_LBA_THE_LBA); print_Data_Buffer(displaySector, deviceList[deviceIter].drive_info.deviceBlockSize, true); } else { - printf("Error Reading LBA %"PRIu64" for display\n", DISPLAY_LBA_THE_LBA); + printf("Error Reading LBA %" PRIu64 " for display\n", DISPLAY_LBA_THE_LBA); exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(displaySector) + safe_free_aligned(&displaySector); } if (BUFFER_TEST_FLAG) @@ -1104,7 +1193,7 @@ int32_t main(int argc, char *argv[]) { printf("Starting short generic test.\n"); } - switch (short_Generic_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, NULL, NULL, HIDE_LBA_COUNTER)) + switch (short_Generic_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1134,7 +1223,7 @@ int32_t main(int argc, char *argv[]) { printf("Starting two minute generic test.\n"); } - switch (two_Minute_Generic_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, NULL, NULL, HIDE_LBA_COUNTER)) + switch (two_Minute_Generic_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1164,11 +1253,11 @@ int32_t main(int argc, char *argv[]) { printf("Starting long generic test.\n"); } - if(ERROR_LIMIT_LOGICAL_COUNT) + if (ERROR_LIMIT_LOGICAL_COUNT) { ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); } - switch (long_Generic_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, NULL, NULL, HIDE_LBA_COUNTER)) + switch (long_Generic_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1230,13 +1319,13 @@ int32_t main(int argc, char *argv[]) { if (VERBOSITY_QUIET < toolVerbosity) { - printf("Starting user generic test starting at LBA %"PRIu64" for the range %"PRIu64"\n", USER_GENERIC_START_FLAG, localRange); + printf("Starting user generic test starting at LBA %" PRIu64 " for the range %" PRIu64 "\n", USER_GENERIC_START_FLAG, localRange); } - if(ERROR_LIMIT_LOGICAL_COUNT) + if (ERROR_LIMIT_LOGICAL_COUNT) { ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); } - switch (user_Sequential_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, USER_GENERIC_START_FLAG, localRange, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, NULL, NULL, HIDE_LBA_COUNTER)) + switch (user_Sequential_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), USER_GENERIC_START_FLAG, localRange, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1288,17 +1377,19 @@ int32_t main(int argc, char *argv[]) if (VERBOSITY_QUIET < toolVerbosity) { uint16_t days = 0; - uint8_t hours = 0, minutes = 0, seconds = 0; - convert_Seconds_To_Displayable_Time(timeInSeconds, NULL, &days, &hours, &minutes, &seconds); + uint8_t hours = 0; + uint8_t minutes = 0; + uint8_t seconds = 0; + convert_Seconds_To_Displayable_Time(timeInSeconds, M_NULLPTR, &days, &hours, &minutes, &seconds); printf("Starting user generic timed test at LBA %" PRIu64 " for", USER_GENERIC_START_FLAG); - print_Time_To_Screen(NULL, &days, &hours, &minutes, &seconds); + print_Time_To_Screen(M_NULLPTR, &days, &hours, &minutes, &seconds); printf("\n"); } if (ERROR_LIMIT_LOGICAL_COUNT) { ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); } - switch (user_Timed_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, USER_GENERIC_START_FLAG, timeInSeconds, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, NULL, NULL, HIDE_LBA_COUNTER)) + switch (user_Timed_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), USER_GENERIC_START_FLAG, timeInSeconds, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1325,12 +1416,12 @@ int32_t main(int argc, char *argv[]) if (RANDOM_READ_TEST_FLAG) { - time_t randomReadSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * 60) + (HOURS_TIME_FLAG * 3600); + uint64_t randomReadSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * UINT64_C(60)) + (HOURS_TIME_FLAG * UINT64_C(3600)); if (VERBOSITY_QUIET < toolVerbosity) { printf("Starting Random test\n"); } - switch (random_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, randomReadSeconds, NULL, NULL, HIDE_LBA_COUNTER)) + switch (random_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), randomReadSeconds, M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1356,12 +1447,12 @@ int32_t main(int argc, char *argv[]) if (BUTTERFLY_READ_TEST_FLAG) { - time_t butterflyTestSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * 60) + (HOURS_TIME_FLAG * 3600); + uint64_t butterflyTestSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * UINT64_C(60)) + (HOURS_TIME_FLAG * UINT64_C(3600)); if (VERBOSITY_QUIET < toolVerbosity) { printf("Starting Buttefly test.\n"); } - switch (butterfly_Test(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, butterflyTestSeconds, NULL, NULL, HIDE_LBA_COUNTER)) + switch (butterfly_Test(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), butterflyTestSeconds, M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1393,18 +1484,18 @@ int32_t main(int argc, char *argv[]) //this will convert the byte size to the nearest logical block (rounding up) localRange = ((localRange + deviceList[deviceIter].drive_info.deviceBlockSize) - 1) / deviceList[deviceIter].drive_info.deviceBlockSize; } - uint64_t OdMdIdTestSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * 60) + (HOURS_TIME_FLAG * 3600); + uint64_t OdMdIdTestSeconds = SECONDS_TIME_FLAG + (MINUTES_TIME_FLAG * UINT64_C(60)) + (HOURS_TIME_FLAG * UINT64_C(3600)); if (localRange > 0) { if (VERBOSITY_QUIET < toolVerbosity) { printf("Starting diameter test\n"); } - if(ERROR_LIMIT_LOGICAL_COUNT) + if (ERROR_LIMIT_LOGICAL_COUNT) { ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); } - switch (diameter_Test_Range(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, PERFORM_OD_TEST, PERFORM_MD_TEST, PERFORM_ID_TEST, localRange, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, NULL, NULL, HIDE_LBA_COUNTER)) + switch (diameter_Test_Range(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), PERFORM_OD_TEST, PERFORM_MD_TEST, PERFORM_ID_TEST, localRange, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, M_NULLPTR, M_NULLPTR, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1431,11 +1522,11 @@ int32_t main(int argc, char *argv[]) else if (OdMdIdTestSeconds > 0) { //run a timed OD MD ID test - if(ERROR_LIMIT_LOGICAL_COUNT) + if (ERROR_LIMIT_LOGICAL_COUNT) { ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); } - switch (diameter_Test_Time(&deviceList[deviceIter], GENERIC_TEST_MODE_FLAG, PERFORM_OD_TEST, PERFORM_MD_TEST, PERFORM_ID_TEST, OdMdIdTestSeconds, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, HIDE_LBA_COUNTER)) + switch (diameter_Test_Time(&deviceList[deviceIter], C_CAST(eRWVCommandType, GENERIC_TEST_MODE_FLAG), PERFORM_OD_TEST, PERFORM_MD_TEST, PERFORM_ID_TEST, OdMdIdTestSeconds, ERROR_LIMIT_FLAG, STOP_ON_ERROR_FLAG, REPAIR_ON_FLY_FLAG, REPAIR_AT_END_FLAG, HIDE_LBA_COUNTER)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1471,7 +1562,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1515,7 +1606,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); diff --git a/utils/C/openSeaChest/openSeaChest_Info.c b/utils/C/openSeaChest/openSeaChest_Info.c index ae05a6f7..2b7dc7be 100644 --- a/utils/C/openSeaChest/openSeaChest_Info.c +++ b/utils/C/openSeaChest/openSeaChest_Info.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,13 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -31,11 +34,12 @@ #include "csmi_helper_func.h" #endif #include "partition_info.h" +#include "sata_phy.h" //////////////////////// // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Info"; -const char *buildVersion = "2.5.0"; +const char *buildVersion = "2.7.0"; //////////////////////////// // functions to declare // @@ -55,14 +59,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -96,8 +100,9 @@ int32_t main(int argc, char *argv[]) SHOW_CONCURRENT_RANGES_VAR LOWLEVEL_INFO_VAR PARTITION_INFO_VAR + SHOW_PHY_EVENT_COUNTERS_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -138,6 +143,7 @@ int32_t main(int argc, char *argv[]) #endif SHOW_CONCURRENT_RANGES_LONG_OPT, PARTITION_INFO_LONG_OPT, + SHOW_PHY_EVENT_COUNTERS_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -174,7 +180,7 @@ int32_t main(int argc, char *argv[]) { case 0: //parse long options that have no short option and required arguments here - if (strncmp(longopts[optionIndex].name, SMART_ATTRIBUTES_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_ATTRIBUTES_LONG_OPT_STRING))) == 0) + if (strcmp(longopts[optionIndex].name, SMART_ATTRIBUTES_LONG_OPT_STRING) == 0) { SMART_ATTRIBUTES_FLAG = true; if (strcmp(optarg, "raw") == 0) @@ -191,11 +197,11 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SCSI_DEFECTS_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SCSI_DEFECTS_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SCSI_DEFECTS_LONG_OPT_STRING) == 0) { size_t counter = 0; SCSI_DEFECTS_FLAG = true; - while (counter < strlen(optarg)) + while (counter < safe_strlen(optarg)) { if (optarg[counter] == 'p' || optarg[counter] == 'P') { @@ -214,14 +220,9 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING) == 0) { - //check for integer value or string that specifies the correct mode. - if (strlen(optarg) == 1 && isdigit(optarg[0])) - { - SCSI_DEFECTS_DESCRIPTOR_MODE = atoi(optarg); - } - else + if (!get_And_Validate_Integer_Input_I(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_DEFECTS_DESCRIPTOR_MODE)) { if (strcmp("shortBlock", optarg) == 0) { @@ -254,22 +255,22 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -338,9 +339,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -377,7 +379,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -474,7 +476,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -530,6 +532,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -559,6 +563,7 @@ int32_t main(int argc, char *argv[]) #endif || SHOW_CONCURRENT_RANGES || PARTITION_INFO_FLAG + || SHOW_PHY_EVENT_COUNTERS )) { utility_Usage(true); @@ -567,7 +572,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -610,7 +615,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -658,11 +663,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -686,7 +691,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -728,7 +733,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -753,7 +758,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -793,6 +798,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -880,7 +894,7 @@ int32_t main(int argc, char *argv[]) if (SMART_ATTRIBUTES_FLAG) { - switch (print_SMART_Attributes(&deviceList[deviceIter], SMART_ATTRIBUTES_MODE_FLAG)) + switch (print_SMART_Attributes(&deviceList[deviceIter], C_CAST(eSMARTAttrOutMode, SMART_ATTRIBUTES_MODE_FLAG))) { case SUCCESS: //nothing to print here since if it was successful, the attributes will be printed to the screen @@ -910,6 +924,16 @@ int32_t main(int argc, char *argv[]) { case SUCCESS: print_DeviceStatistics(&deviceList[deviceIter], &deviceStats); + //if supported then print Seagate Device Statistics also + if (is_Seagate_DeviceStatistics_Supported(&deviceList[deviceIter])) + { + seagateDeviceStatistics seagateDeviceStats; + memset(&seagateDeviceStats, 0, sizeof(seagateDeviceStatistics)); + if (SUCCESS == get_Seagate_DeviceStatistics(&deviceList[deviceIter], &seagateDeviceStats)) + { + print_Seagate_DeviceStatistics(&deviceList[deviceIter], &seagateDeviceStats); + } + } break; case NOT_SUPPORTED: if (VERBOSITY_QUIET < toolVerbosity) @@ -930,8 +954,8 @@ int32_t main(int argc, char *argv[]) if (SCSI_DEFECTS_FLAG) { - ptrSCSIDefectList defects = NULL; - switch (get_SCSI_Defect_List(&deviceList[deviceIter], SCSI_DEFECTS_DESCRIPTOR_MODE, SCSI_DEFECTS_GROWN_LIST, SCSI_DEFECTS_PRIMARY_LIST, &defects)) + ptrSCSIDefectList defects = M_NULLPTR; + switch (get_SCSI_Defect_List(&deviceList[deviceIter], C_CAST(eSCSIAddressDescriptors, SCSI_DEFECTS_DESCRIPTOR_MODE), SCSI_DEFECTS_GROWN_LIST, SCSI_DEFECTS_PRIMARY_LIST, &defects)) { case SUCCESS: print_SCSI_Defect_List(defects); @@ -982,10 +1006,36 @@ int32_t main(int argc, char *argv[]) } } + if (SHOW_PHY_EVENT_COUNTERS) + { + sataPhyEventCounters events; + memset(&events, 0, sizeof(sataPhyEventCounters)); + switch (get_SATA_Phy_Event_Counters(&deviceList[deviceIter], &events)) + { + case SUCCESS: + print_SATA_Phy_Event_Counters(&events); + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Phy event counters are not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to read the Phy event counters.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1024,7 +1074,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -1072,6 +1122,7 @@ void utility_Usage(bool shortUsage) print_Partition_Info_Help(shortUsage); //SATA Only Options printf("\n\tSATA Only:\n\t=========\n"); + print_Show_Phy_Event_Counters_Help(shortUsage); print_SMART_Attributes_Help(shortUsage); //SAS Only Options printf("\n\tSAS Only:\n\t=========\n"); diff --git a/utils/C/openSeaChest/openSeaChest_Logs.c b/utils/C/openSeaChest/openSeaChest_Logs.c index 8a7b0c05..6ec7ffb0 100644 --- a/utils/C/openSeaChest/openSeaChest_Logs.c +++ b/utils/C/openSeaChest/openSeaChest_Logs.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -15,11 +16,14 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "secure_file.h" + #include "getopt.h" #include "common_public.h" #include "EULA.h" @@ -29,12 +33,13 @@ #include "logs.h" #include "farm_log.h" #include "drive_info.h" +#include "smart.h" //////////////////////// // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Logs"; -const char *buildVersion = "2.4.0"; +const char *buildVersion = "2.5.0"; //////////////////////////// // functions to declare // @@ -55,14 +60,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS OUTPUTPATH_VAR DEVICE_INFO_VAR @@ -109,7 +114,7 @@ int32_t main(int argc, char *argv[]) LOG_LENGTH_BYTES_VAR LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -195,13 +200,11 @@ int32_t main(int argc, char *argv[]) switch (args) { case 0: - if (strncmp(longopts[optionIndex].name, GENERIC_LOG_LONG_OPT_STRING, strlen(GENERIC_LOG_LONG_OPT_STRING)) == 0) + if (strcmp(longopts[optionIndex].name, GENERIC_LOG_LONG_OPT_STRING) == 0) { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &temp)) + if (get_And_Validate_Integer_Input_Uint8(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &GENERIC_LOG_DATA_SET)) { GENERIC_LOG_PULL_FLAG = true; - GENERIC_LOG_DATA_SET = C_CAST(uint8_t, temp); } else { @@ -209,23 +212,17 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, GENERIC_LOG_SUBPAGE_LONG_OPT_STRING, strlen(GENERIC_LOG_SUBPAGE_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, GENERIC_LOG_SUBPAGE_LONG_OPT_STRING) == 0) { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &temp)) - { - //no need to do anything...this option requires that the page is also given - GENERIC_LOG_SUBPAGE_DATA_SET = C_CAST(uint8_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Uint8(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &GENERIC_LOG_SUBPAGE_DATA_SET)) { print_Error_In_Cmd_Line_Args(GENERIC_LOG_SUBPAGE_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, GENERIC_ERROR_HISTORY_LONG_OPT_STRING, strlen(GENERIC_ERROR_HISTORY_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, GENERIC_ERROR_HISTORY_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &GENERIC_ERROR_HISTORY_BUFFER_ID)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &GENERIC_ERROR_HISTORY_BUFFER_ID)) { GENERIC_ERROR_HISTORY_PULL_FLAG = true; } @@ -235,95 +232,111 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, LOG_TRANSFER_LENGTH_LONG_OPT_STRING, strlen(LOG_TRANSFER_LENGTH_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, LOG_TRANSFER_LENGTH_LONG_OPT_STRING) == 0) { - //set the raw data length - but check the units first! - uint64_t multiplier = 1; - uint64_t optargInt = C_CAST(uint64_t, atoll(optarg)); - if (strstr(optarg, "BLOCKS") || strstr(optarg, "SECTORS")) - { - //they specified blocks. For log transfers this means a number of 512B sectors - multiplier = LEGACY_DRIVE_SEC_SIZE; - } - else if (strstr(optarg, "KB")) - { - multiplier = UINT64_C(1000); - } - else if (strstr(optarg, "KiB")) - { - multiplier = UINT64_C(1024); - } - else if (strstr(optarg, "MB")) - { - multiplier = UINT64_C(1000000); - } - else if (strstr(optarg, "MiB")) - { - multiplier = UINT64_C(1048576); - } - else if (strstr(optarg, "GB")) - { - multiplier = UINT64_C(1000000000); - } - else if (strstr(optarg, "GiB")) - { - multiplier = UINT64_C(1073741824); - } - else if (strstr(optarg, "TB")) + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_DATASIZE, &LOG_TRANSFER_LENGTH_BYTES)) { - multiplier = UINT64_C(1000000000000); + //Check to see if any units were specified, otherwise assume LBAs + uint32_t multiplier = 1; + if (unit) + { + if (strcmp(unit, "") == 0) + { + multiplier = 1;//no additional units provided, so do not treat as an error + } + else if (strcmp(unit, "BLOCKS") == 0 || strcmp(unit, "SECTORS") == 0) + { + //they specified blocks. For log transfers this means a number of 512B sectors + multiplier = LEGACY_DRIVE_SEC_SIZE; + } + else if (strcmp(unit, "KB") == 0) + { + multiplier = UINT64_C(1000); + } + else if (strcmp(unit, "KiB") == 0) + { + multiplier = UINT64_C(1024); + } + else if (strcmp(unit, "MB") == 0) + { + multiplier = UINT64_C(1000000); + } + else if (strcmp(unit, "MiB") == 0) + { + multiplier = UINT64_C(1048576); + } + else + { + print_Error_In_Cmd_Line_Args(LOG_TRANSFER_LENGTH_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + LOG_TRANSFER_LENGTH_BYTES *= multiplier; } - else if (strstr(optarg, "TiB")) + else { - multiplier = UINT64_C(1099511627776); + print_Error_In_Cmd_Line_Args(LOG_TRANSFER_LENGTH_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - LOG_TRANSFER_LENGTH_BYTES = C_CAST(uint32_t, optargInt * multiplier); } else if (strcmp(longopts[optionIndex].name, LOG_LENGTH_LONG_OPT_STRING) == 0) { - //set the raw data length - but check the units first! - uint64_t multiplier = 1; - uint32_t optargInt = C_CAST(uint32_t, atoi(optarg)); - if (strstr(optarg, "BLOCKS") || strstr(optarg, "SECTORS")) - { - //they specified blocks. For log transfers this means a number of 512B sectors - multiplier = LEGACY_DRIVE_SEC_SIZE; - } - else if (strstr(optarg, "KB")) - { - multiplier = 1000; - } - else if (strstr(optarg, "KiB")) + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_DATASIZE, &LOG_LENGTH_BYTES)) { - multiplier = 1024; - } - else if (strstr(optarg, "MB")) - { - multiplier = 1000000; - } - else if (strstr(optarg, "MiB")) - { - multiplier = 1048576; - } - else if (strstr(optarg, "GB")) - { - multiplier = 1000000000; - } - else if (strstr(optarg, "GiB")) - { - multiplier = 1073741824; - } - else if (strstr(optarg, "TB")) - { - multiplier = 1000000000000; + //Check to see if any units were specified, otherwise assume LBAs + uint32_t multiplier = 1; + if (unit) + { + if (strcmp(unit, "") == 0) + { + multiplier = 1;//no additional units provided, so do not treat as an error + } + else if (strcmp(unit, "BLOCKS") == 0 || strcmp(unit, "SECTORS") == 0) + { + //they specified blocks. For log transfers this means a number of 512B sectors + multiplier = LEGACY_DRIVE_SEC_SIZE; + } + else if (strcmp(unit, "KB") == 0) + { + multiplier = UINT32_C(1000); + } + else if (strcmp(unit, "KiB") == 0) + { + multiplier = UINT32_C(1024); + } + else if (strcmp(unit, "MB") == 0) + { + multiplier = UINT32_C(1000000); + } + else if (strcmp(unit, "MiB") == 0) + { + multiplier = UINT32_C(1048576); + } + else if (strcmp(unit, "GB") == 0) + { + multiplier = UINT32_C(1000000000); + } + else if (strcmp(unit, "GiB") == 0) + { + multiplier = UINT32_C(1073741824); + } + else + { + print_Error_In_Cmd_Line_Args(LOG_LENGTH_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + LOG_LENGTH_BYTES *= multiplier; } - else if (strstr(optarg, "TiB")) + else { - multiplier = 1099511627776; + print_Error_In_Cmd_Line_Args(LOG_LENGTH_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - LOG_LENGTH_BYTES = C_CAST(uint32_t, optargInt * multiplier); } - else if (strncmp(longopts[optionIndex].name, PATH_LONG_OPT_STRING, strlen(longopts[optionIndex].name)) == 0) + else if (strcmp(longopts[optionIndex].name, PATH_LONG_OPT_STRING) == 0) { OUTPUTPATH_PARSE if (!os_Directory_Exists(OUTPUTPATH_FLAG)) @@ -331,29 +344,28 @@ int32_t main(int argc, char *argv[]) printf("Err: --outputPath %s does not exist\n", OUTPUTPATH_FLAG); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, strlen(MODEL_MATCH_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, strlen(FW_MATCH_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, strlen(CHILD_FW_MATCH_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, PULL_LOG_MODE_LONG_OPT_STRING, strlen(PULL_LOG_MODE_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, PULL_LOG_MODE_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "raw") == 0) { @@ -378,7 +390,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SATA_FARM_COPY_TYPE_LONG_OPT_STRING, strlen(SATA_FARM_COPY_TYPE_LONG_OPT_STRING)) == 0) + else if (strcmp(longopts[optionIndex].name, SATA_FARM_COPY_TYPE_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "disc") == 0) { @@ -394,7 +406,6 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - //parse long options that have required args here. break; case DEVICE_SHORT_OPT: //device if (0 != parse_Device_Handle_Argument(optarg, &RUN_ON_ALL_DRIVES, &USER_PROVIDED_HANDLE, &DEVICE_LIST_COUNT, &HANDLE_LIST)) @@ -421,9 +432,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -460,7 +472,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -491,7 +503,7 @@ int32_t main(int argc, char *argv[]) print_Elevated_Privileges_Text(); } unsigned int scanControl = DEFAULT_SCAN; - if(AGRESSIVE_SCAN_FLAG) + if (AGRESSIVE_SCAN_FLAG) { scanControl |= AGRESSIVE_SCAN; } @@ -557,7 +569,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -613,6 +625,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -632,7 +646,7 @@ int32_t main(int argc, char *argv[]) //check that we were given at least one test to perform...if not, show the help and exit if (!(DEVICE_INFO_FLAG || TEST_UNIT_READY_FLAG - || LOWLEVEL_INFO_FLAG + || LOWLEVEL_INFO_FLAG || LIST_LOGS_FLAG || LIST_ERROR_HISTORY_FLAG || GENERIC_LOG_PULL_FLAG @@ -652,7 +666,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -695,7 +709,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -743,11 +757,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; -#elif !defined(_WIN32) + deviceList[handleIter].os_info.fd = M_NULLPTR; +#elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -765,33 +779,34 @@ int32_t main(int argc, char *argv[]) #if defined(_DEBUG) printf("Attempting to open handle \"%s\"\n", HANDLE_LIST[handleIter]); #endif - ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); + + ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); #if !defined(_WIN32) #if !defined(VMK_CROSS_COMP) - if ((deviceList[handleIter].os_info.fd < 0) || + if ((deviceList[handleIter].os_info.fd < 0) || #else - if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + if (((deviceList[handleIter].os_info.fd < 0) && + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif - (ret == FAILURE || ret == PERMISSION_DENIED)) + (ret == FAILURE || ret == PERMISSION_DENIED)) #else - if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) + if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) #endif - { - if (VERBOSITY_QUIET < toolVerbosity) { - printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); - } - free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); - if(ret == PERMISSION_DENIED || !is_Running_Elevated()) - { - exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); - } - else - { - exit(UTIL_EXIT_OPERATION_FAILURE); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } } - } } } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); @@ -813,7 +828,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -837,7 +852,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -876,6 +891,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -913,7 +937,7 @@ int32_t main(int argc, char *argv[]) if (PULL_LOG_MODE != PULL_LOG_PIPE_MODE) { printf("\n%s - %s - %s - %s - %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification, deviceList[deviceIter].drive_info.serialNumber, deviceList[deviceIter].drive_info.product_revision, print_drive_type(&deviceList[deviceIter])); - } + } } //now start looking at what operations are going to be performed and kick them off @@ -1013,7 +1037,7 @@ int32_t main(int argc, char *argv[]) } else { - printf("\nLog %" PRIu8 " not supported by %s\n",\ + printf("\nLog %" PRIu8 " not supported by %s\n", \ GENERIC_LOG_DATA_SET, deviceList[deviceIter].drive_info.serialNumber); } } @@ -1069,7 +1093,7 @@ int32_t main(int argc, char *argv[]) case MEMORY_FAILURE: if (VERBOSITY_QUIET < toolVerbosity) { - printf("\nFailed to allocate memory for buffer ID %"PRIu64"\n", GENERIC_ERROR_HISTORY_BUFFER_ID); + printf("\nFailed to allocate memory for buffer ID %" PRIu64 "\n", GENERIC_ERROR_HISTORY_BUFFER_ID); } exitCode = UTIL_EXIT_OPERATION_FAILURE; break; @@ -1084,7 +1108,8 @@ int32_t main(int argc, char *argv[]) if (FARM_PULL_FLAG) { - switch (pull_FARM_Log(&deviceList[deviceIter], OUTPUTPATH_FLAG, LOG_TRANSFER_LENGTH_BYTES, 0, SEAGATE_ATA_LOG_FIELD_ACCESSIBLE_RELIABILITY_METRICS, PULL_LOG_MODE)) + //PULL_FARM_FACTORY_PAGE_FLAG + switch (pull_FARM_Log(&deviceList[deviceIter], OUTPUTPATH_FLAG, LOG_TRANSFER_LENGTH_BYTES, 0, SEAGATE_ATA_LOG_FIELD_ACCESSIBLE_RELIABILITY_METRICS, PULL_LOG_BIN_FILE_MODE)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1098,7 +1123,14 @@ int32_t main(int argc, char *argv[]) case NOT_SUPPORTED: if (VERBOSITY_QUIET < toolVerbosity) { - printf("FARM log not supported on this device\n"); + // if (0) + // { + // printf("Factory FARM Page not supported on this device\n"); + // } + // else + { + printf("FARM log not supported on this device\n"); + } } exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; break; @@ -1272,9 +1304,10 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } + //----------------------------------------------------------------------------- // // Utility_usage() @@ -1295,7 +1328,7 @@ void utility_Usage(bool shortUsage) printf("=====\n"); printf("\t %s [-d %s] {arguments} {options}\n\n", util_name, deviceHandleName); - printf("Examples\n"); + printf("\nExamples\n"); printf("========\n"); //example usage printf("\t%s --%s\n", util_name, SCAN_LONG_OPT_STRING); @@ -1304,7 +1337,7 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, LOWLEVEL_INFO_LONG_OPT_STRING); printf("\t%s -d %s --%s --%s logs --%s pipe\n", util_name, deviceHandleExample, FARM_LONG_OPT_STRING, PATH_LONG_OPT_STRING, PULL_LOG_MODE_LONG_OPT_STRING); printf("\t%s -d %s --%s --%s 64KiB --%s bin\n", util_name, deviceHandleExample, FARM_COMBINED_LONG_OPT_STRING, LOG_TRANSFER_LENGTH_LONG_OPT_STRING, PULL_LOG_MODE_LONG_OPT_STRING); - printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, DEVICE_STATISTICS_LONG_OPT_STRING); + printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, DEVICE_STATISTICS_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, LIST_LOGS_LONG_OPT_STRING); printf("\t%s -d %s --%s C6h\n", util_name, deviceHandleExample, GENERIC_LOG_LONG_OPT_STRING); printf("\t%s -d %s --%s 0Dh --%s 01h --%s bin\n", util_name, deviceHandleExample, GENERIC_LOG_LONG_OPT_STRING, GENERIC_LOG_SUBPAGE_LONG_OPT_STRING, PULL_LOG_MODE_LONG_OPT_STRING); @@ -1314,7 +1347,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); diff --git a/utils/C/openSeaChest/openSeaChest_NVMe.c b/utils/C/openSeaChest/openSeaChest_NVMe.c index a0080037..caadae43 100644 --- a/utils/C/openSeaChest/openSeaChest_NVMe.c +++ b/utils/C/openSeaChest/openSeaChest_NVMe.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // openSeaChest_NVMe.c // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -13,11 +14,17 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "precision_timer.h" +#include "secure_file.h" +#include "sleep.h" +#include "math_utils.h" + #include "getopt.h" #include <math.h> #include "EULA.h" @@ -35,7 +42,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_NVMe"; -const char *buildVersion = "2.3.0"; +const char *buildVersion = "2.4.0"; //////////////////////////// // functions to declare // @@ -55,14 +62,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -85,6 +92,7 @@ int32_t main(int argc, char *argv[]) NEW_FW_MATCH_VARS CHECK_POWER_VAR TRANSITION_POWER_STATE_VAR + SHOW_NVM_POWER_STATES_VAR GET_NVME_LOG_VAR GET_TELEMETRY_VAR TELEMETRY_DATA_AREA_VAR @@ -107,8 +115,14 @@ int32_t main(int argc, char *argv[]) PROGRESS_VAR SHOW_SUPPORTED_FORMATS_VAR LOWLEVEL_INFO_VAR + LIST_LOGS_VAR + FORCE_DRIVE_TYPE_VARS + +#if defined (ENABLE_HWRAID_SUPPORT) + RAID_PHYSICAL_DRIVE rDevice;//TODO: This should be a list so that we can talk to more than one raid device at a time! +#endif - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -143,6 +157,7 @@ int32_t main(int argc, char *argv[]) FIRMWARE_SLOT_BUFFER_ID_LONG_OPT, CHECK_POWER_LONG_OPT, TRANSITION_POWER_STATE_LONG_OPT, + SHOW_NVM_POWER_STATES_LONG_OPT, GET_NVME_LOG_LONG_OPT, GET_TELEMETRY_LONG_OPT, TELEMETRY_DATA_AREA_LONG_OPT, @@ -152,14 +167,16 @@ int32_t main(int argc, char *argv[]) EXT_SMART_LOG_LONG_OPT1, MODEL_MATCH_LONG_OPT, FW_MATCH_LONG_OPT, -// CHILD_MODEL_MATCH_LONG_OPT, -// CHILD_FW_MATCH_LONG_OPT, + //CHILD_MODEL_MATCH_LONG_OPT, + //CHILD_FW_MATCH_LONG_OPT, CLEAR_PCIE_CORRECTABLE_ERRORS_LONG_OPT, NVME_TEMP_STATS_LONG_OPT, NVME_PCI_STATS_LONG_OPT, SHOW_SUPPORTED_FORMATS_LONG_OPT, NVM_FORMAT_LONG_OPT, NVM_FORMAT_OPTIONS_LONG_OPTS, + LIST_LOGS_LONG_OPT, + FORCE_DRIVE_TYPE_LONG_OPTS, LONG_OPT_TERMINATOR }; @@ -200,18 +217,18 @@ int32_t main(int argc, char *argv[]) //parse long options that have no short option and required arguments here if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { - if (strlen(optarg) == strlen(DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, DATA_ERASE_ACCEPT_STRING, strlen(DATA_ERASE_ACCEPT_STRING)) == 0) + if (strcmp(optarg, DATA_ERASE_ACCEPT_STRING) == 0) { DATA_ERASE_FLAG = true; } } else if (strcmp(longopts[optionIndex].name, OUTPUT_MODE_LONG_OPT_STRING) == 0) { - if (strncmp(optarg, "raw", strlen(optarg)) == 0) + if (strcmp(optarg, "raw") == 0) { OUTPUT_MODE_IDENTIFIER = UTIL_OUTPUT_MODE_RAW; } - else if (strncmp(optarg, "binary", strlen(optarg)) == 0) + else if (strcmp(optarg, "binary") == 0) { OUTPUT_MODE_IDENTIFIER = UTIL_OUTPUT_MODE_BIN; } @@ -224,22 +241,17 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, GET_FEATURES_LONG_OPT_STRING) == 0) { - uint64_t temp = 0; GET_FEATURES_FLAG = true; - if (strncmp(optarg, "help", strlen(optarg)) == 0) + if (strcmp(optarg, "help") == 0) { nvme_Print_Feature_Identifiers_Help(); exit(UTIL_EXIT_NO_ERROR); } - else if (strncmp(optarg, "list", strlen(optarg)) == 0) + else if (strcmp(optarg, "list") == 0) { GET_FEATURES = UINT16_MAX;//set a value higher than is possible to request to know it is invalid and requesting the list } - else if (get_And_Validate_Integer_Input(optarg, &temp)) - { - GET_FEATURES = C_CAST(uint8_t, temp); - } - else + else if (!get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &GET_FEATURES)) { print_Error_In_Cmd_Line_Args(GET_FEATURES_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -256,8 +268,8 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, DOWNLOAD_FW_LONG_OPT_STRING) == 0) { - int scanRet = sscanf(optarg, FIRMWARE_FILE_NAME_MAX_LEN_FORMAT_STR, DOWNLOAD_FW_FILENAME_FLAG); - if (scanRet > 0 && scanRet != EOF) + int res = snprintf(DOWNLOAD_FW_FILENAME_FLAG, FIRMWARE_FILE_NAME_MAX_LEN, "%s", optarg); + if (res > 0 && res <= FIRMWARE_FILE_NAME_MAX_LEN) { DOWNLOAD_FW_FLAG = true; } @@ -267,7 +279,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, DOWNLOAD_FW_MODE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(DOWNLOAD_FW_MODE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, DOWNLOAD_FW_MODE_LONG_OPT_STRING) == 0) { DOWNLOAD_FW_MODE = FWDL_UPDATE_MODE_AUTOMATIC; if (strcmp(optarg, "immediate") == 0 || strcmp(optarg, "full") == 0) @@ -303,13 +315,19 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, FWDL_SEGMENT_SIZE_LONG_OPT_STRING) == 0) { - FWDL_SEGMENT_SIZE_FROM_USER = true; - FWDL_SEGMENT_SIZE_FLAG = C_CAST(uint16_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FWDL_SEGMENT_SIZE_FLAG)) + { + FWDL_SEGMENT_SIZE_FROM_USER = true; + } + else + { + print_Error_In_Cmd_Line_Args(FWDL_SEGMENT_SIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, FIRMWARE_SLOT_LONG_OPT_STRING) == 0 || strcmp(longopts[optionIndex].name, FIRMWARE_BUFFER_ID_LONG_OPT_STRING) == 0) { - FIRMWARE_SLOT_FLAG = C_CAST(uint8_t, atoi(optarg)); - if (FIRMWARE_SLOT_FLAG > 7) + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &FIRMWARE_SLOT_FLAG) || FIRMWARE_SLOT_FLAG > 7) { if (toolVerbosity > VERBOSITY_QUIET) { @@ -320,35 +338,33 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TRANSITION_POWER_STATE_LONG_OPT_STRING) == 0) { - //set the timer value - TRANSITION_POWER_STATE_TO = atoi(optarg); + if (!get_And_Validate_Integer_Input_Int32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &TRANSITION_POWER_STATE_TO)) + { + print_Error_In_Cmd_Line_Args(TRANSITION_POWER_STATE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, GET_NVME_LOG_LONG_OPT_STRING) == 0) { - //set the power mode - if (isdigit(optarg[0]))//this will get the valid NVMe power levels + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &GET_NVME_LOG_IDENTIFIER)) { - GET_NVME_LOG_IDENTIFIER = C_CAST(uint8_t, atoi(optarg)); - } - else - { - if (strncmp("error", optarg, strlen(optarg)) == 0) + if (strcmp("error", optarg) == 0) { GET_NVME_LOG_IDENTIFIER = NVME_LOG_ERROR_ID; } - else if (strncmp("smart", optarg, strlen(optarg)) == 0 || strncmp("SMART", optarg, strlen(optarg)) == 0) + else if (strcasecmp("smart", optarg) == 0) { GET_NVME_LOG_IDENTIFIER = NVME_LOG_SMART_ID; } - else if (strncmp("fwSlots", optarg, strlen(optarg)) == 0) + else if (strcmp("fwSlots", optarg) == 0) { GET_NVME_LOG_IDENTIFIER = NVME_LOG_FW_SLOT_ID; } - else if (strncmp("suppCmds", optarg, strlen(optarg)) == 0) + else if (strcmp("suppCmds", optarg) == 0) { GET_NVME_LOG_IDENTIFIER = NVME_LOG_CMD_SPT_EFET_ID; } - else if (strncmp("selfTest", optarg, strlen(optarg)) == 0) + else if (strcmp("selfTest", optarg) == 0) { GET_NVME_LOG_IDENTIFIER = NVME_LOG_DEV_SELF_TEST_ID; } @@ -361,11 +377,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, GET_TELEMETRY_LONG_OPT_STRING) == 0) { - if (strncmp("host", optarg, strlen(optarg)) == 0) + if (strcmp("host", optarg) == 0) { GET_TELEMETRY_IDENTIFIER = NVME_LOG_TELEMETRY_HOST_ID; } - else if (strncmp("ctrl", optarg, strlen(optarg)) == 0) + else if (strcmp("ctrl", optarg) == 0) { GET_TELEMETRY_IDENTIFIER = NVME_LOG_TELEMETRY_CTRL_ID; } @@ -377,12 +393,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TELEMETRY_DATA_AREA_LONG_OPT_STRING) == 0) { - //set the telemetry data area - if (isdigit(optarg[0]))//this will get the valid NVMe telemetry data area - { - TELEMETRY_DATA_AREA = C_CAST(uint8_t, atoi(optarg)); - } - else + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &TELEMETRY_DATA_AREA)) { print_Error_In_Cmd_Line_Args(TELEMETRY_DATA_AREA_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -394,7 +405,11 @@ int32_t main(int argc, char *argv[]) if (strcmp(optarg, "current") != 0) { //set the sector size - NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_SECTOR_SIZE_OR_FORMAT_NUM)) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_NSID_LONG_OPT_STRING) == 0) @@ -435,7 +450,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_PI_TYPE_LONG_OPT_STRING) == 0) { - NVM_FORMAT_PI_TYPE = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_PI_TYPE) || NVM_FORMAT_PI_TYPE > 3) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_PI_TYPE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_PI_LOCATION_LONG_OPT_STRING) == 0) { @@ -455,7 +474,11 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING) == 0) { - NVM_FORMAT_METADATA_SIZE = C_CAST(uint32_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &NVM_FORMAT_METADATA_SIZE)) + { + print_Error_In_Cmd_Line_Args(NVM_FORMAT_METADATA_SIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, NVM_FORMAT_METADATA_SETTING_LONG_OPT_STRING) == 0) { @@ -494,7 +517,7 @@ int32_t main(int argc, char *argv[]) switch (optopt) { case 0: - //check long options for missing arguments + //check long options for missing arguments break; case DEVICE_SHORT_OPT: if (VERBOSITY_QUIET < toolVerbosity) @@ -552,9 +575,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case PROGRESS_SHORT_OPT: //get test progress for a specific test @@ -594,7 +618,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -629,7 +653,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= AGRESSIVE_SCAN; } - #if defined (__linux__) +#if defined (__linux__) if (SCAN_FLAGS.scanSD) { scanControl |= SD_HANDLES; @@ -638,7 +662,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SG_TO_SD; } - #endif +#endif //set the drive types to show (if none are set, the lower level code assumes we need to show everything) if (SCAN_FLAGS.scanATA) { @@ -691,7 +715,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -757,23 +781,25 @@ int32_t main(int argc, char *argv[]) } //check that we were given at least one test to perform...if not, set that we are dumping device information so we at least do something if (!(DEVICE_INFO_FLAG - || LOWLEVEL_INFO_FLAG - || DOWNLOAD_FW_FLAG - || ACTIVATE_DEFERRED_FW_FLAG - || SWITCH_FW_FLAG - || TEST_UNIT_READY_FLAG - || CHECK_POWER_FLAG - || (TRANSITION_POWER_STATE_TO >= 0) - || (GET_NVME_LOG_IDENTIFIER > 0) // Since 0 is Reserved - || (GET_TELEMETRY_IDENTIFIER > 0) - || (GET_FEATURES_FLAG) - || EXT_SMART_LOG_FLAG1 - || CLEAR_PCIE_CORRECTABLE_ERRORS_LOG_FLAG - || NVME_TEMP_STATS_FLAG - || NVME_PCI_STATS_FLAG - || SHOW_SUPPORTED_FORMATS_FLAG - || NVM_FORMAT_FLAG - || PROGRESS_CHAR != NULL + || LOWLEVEL_INFO_FLAG + || DOWNLOAD_FW_FLAG + || ACTIVATE_DEFERRED_FW_FLAG + || SWITCH_FW_FLAG + || TEST_UNIT_READY_FLAG + || CHECK_POWER_FLAG + || (TRANSITION_POWER_STATE_TO >= 0) + || SHOW_NVM_POWER_STATES + || (GET_NVME_LOG_IDENTIFIER > 0) // Since 0 is Reserved + || (GET_TELEMETRY_IDENTIFIER > 0) + || (GET_FEATURES_FLAG) + || EXT_SMART_LOG_FLAG1 + || CLEAR_PCIE_CORRECTABLE_ERRORS_LOG_FLAG + || NVME_TEMP_STATS_FLAG + || NVME_PCI_STATS_FLAG + || SHOW_SUPPORTED_FORMATS_FLAG + || NVM_FORMAT_FLAG + || PROGRESS_CHAR != M_NULLPTR + || LIST_LOGS_FLAG //check for other tool specific options here )) { @@ -783,7 +809,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -857,11 +883,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -879,7 +905,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -906,6 +932,15 @@ int32_t main(int argc, char *argv[]) for (uint32_t deviceIter = 0; deviceIter < DEVICE_LIST_COUNT; ++deviceIter) { deviceList[deviceIter].deviceVerbosity = toolVerbosity; + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (ONLY_SEAGATE_FLAG) { if (is_Seagate_Family(&deviceList[deviceIter]) == NON_SEAGATE) @@ -921,7 +956,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -982,30 +1017,53 @@ int32_t main(int argc, char *argv[]) } else if (OUTPUT_MODE_IDENTIFIER == UTIL_OUTPUT_MODE_BIN) { - FILE * pIdentifyFile = NULL; - char identifyFileName[OPENSEA_PATH_MAX] = { 0 }; - char * fileNameUsed = &identifyFileName[0]; - if (SUCCESS == create_And_Open_Log_File(&deviceList[deviceIter], &pIdentifyFile, NULL, \ - "CTRL_IDENTIFY", "bin", 1, &fileNameUsed)) + secureFileInfo *secureFile = M_NULLPTR; + if (SUCCESS == create_And_Open_Secure_Log_File_Dev_EZ(&deviceList[deviceIter], &secureFile, NAMING_SERIAL_NUMBER_DATE_TIME, M_NULLPTR, "CTRL_IDENTIFY", "bin")) { - fwrite(&deviceList[deviceIter].drive_info.IdentifyData.nvme.ctrl, sizeof(uint8_t), sizeof(nvmeIDNameSpaces), pIdentifyFile); - fflush(pIdentifyFile); - fclose(pIdentifyFile); - if (VERBOSITY_QUIET < toolVerbosity) + if (SEC_FILE_SUCCESS == secure_Write_File(secureFile, &deviceList[deviceIter].drive_info.IdentifyData.nvme.ctrl, NVME_IDENTIFY_DATA_LEN, sizeof(uint8_t), NVME_IDENTIFY_DATA_LEN, M_NULLPTR)) { - printf("Created %s file with Controller Information\n", fileNameUsed); + secure_Flush_File(secureFile); + if (SEC_FILE_SUCCESS != secure_Close_File(secureFile)) + { + printf("Error closing file!\n"); + } + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Created %s file with Controller Information\n", secureFile->fullpath); + } } - memset(fileNameUsed, 0, OPENSEA_PATH_MAX); - if (SUCCESS == create_And_Open_Log_File(&deviceList[deviceIter], &pIdentifyFile, NULL, \ - "NAMESPACE_IDENTIFY", "bin", 1, &fileNameUsed)) + else { - fwrite(&deviceList[deviceIter].drive_info.IdentifyData.nvme.ns, sizeof(uint8_t), sizeof(nvmeIDNameSpaces), pIdentifyFile); - fflush(pIdentifyFile); - fclose(pIdentifyFile); if (VERBOSITY_QUIET < toolVerbosity) { - printf("Created %s file with Namespace Information\n", fileNameUsed); + printf("ERROR: failed to open file to write controller identify information\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + free_Secure_File_Info(&secureFile); + if (SUCCESS == create_And_Open_Secure_Log_File_Dev_EZ(&deviceList[deviceIter], &secureFile, NAMING_SERIAL_NUMBER_DATE_TIME, M_NULLPTR, "NAMESPACE_IDENTIFY", "bin")) + { + if (SEC_FILE_SUCCESS == secure_Write_File(secureFile, &deviceList[deviceIter].drive_info.IdentifyData.nvme.ns, NVME_IDENTIFY_DATA_LEN, sizeof(uint8_t), NVME_IDENTIFY_DATA_LEN, M_NULLPTR)) + { + secure_Flush_File(secureFile); + if (SEC_FILE_SUCCESS != secure_Close_File(secureFile)) + { + printf("Error closing file!\n"); + } + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Created %s file with Namespace Information\n", secureFile->fullpath); + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to open file to write namespace information\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; } + free_Secure_File_Info(&secureFile); } else { @@ -1015,7 +1073,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - + free_Secure_File_Info(&secureFile); } else { @@ -1025,6 +1083,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + free_Secure_File_Info(&secureFile); } } @@ -1033,11 +1092,35 @@ int32_t main(int argc, char *argv[]) print_Low_Level_Info(&deviceList[deviceIter]); } + if (LIST_LOGS_FLAG) + { + switch (print_Supported_Logs(&deviceList[deviceIter], 0)) + { + case SUCCESS: + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\nListing supported logs is not supported for device %s.\n", \ + deviceList[deviceIter].drive_info.serialNumber); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\nFailed to list logs for device %s\n", \ + deviceList[deviceIter].drive_info.serialNumber); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + } + if (SHOW_SUPPORTED_FORMATS_FLAG) { uint32_t numberOfSectorSizes = get_Number_Of_Supported_Sector_Sizes(&deviceList[deviceIter]); - uint32_t memSize = sizeof(supportedFormats) + sizeof(sectorSize) * numberOfSectorSizes; - ptrSupportedFormats formats = C_CAST(ptrSupportedFormats, malloc(memSize)); + uint32_t memSize = C_CAST(uint32_t, sizeof(supportedFormats) + sizeof(sectorSize) * numberOfSectorSizes); + ptrSupportedFormats formats = C_CAST(ptrSupportedFormats, safe_malloc(memSize)); if (formats) { memset(formats, 0, memSize); @@ -1062,7 +1145,7 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; break; } - safe_Free(formats); + safe_free_supported_formats(&formats); } else { @@ -1113,23 +1196,25 @@ int32_t main(int argc, char *argv[]) if (OUTPUT_MODE_IDENTIFIER != UTIL_OUTPUT_MODE_HUMAN) { uint64_t size = 0; - uint8_t * logBuffer = NULL; + uint8_t * logBuffer = M_NULLPTR; nvmeGetLogPageCmdOpts cmdOpts; - if ((nvme_Get_Log_Size(&deviceList[deviceIter], GET_NVME_LOG_IDENTIFIER, &size) == SUCCESS) && size) + ret = nvme_Get_Log_Size(&deviceList[deviceIter], GET_NVME_LOG_IDENTIFIER, &size); + if (ret == SUCCESS && size) { memset(&cmdOpts, 0, sizeof(nvmeGetLogPageCmdOpts)); if (NVME_LOG_ERROR_ID == GET_NVME_LOG_IDENTIFIER) { size = 32 * size; //Get first 32 entries. } - logBuffer = C_CAST(uint8_t *, calloc(C_CAST(size_t, size), sizeof(uint8_t))); - if (logBuffer != NULL) + logBuffer = C_CAST(uint8_t *, safe_calloc(C_CAST(size_t, size), sizeof(uint8_t))); + if (logBuffer != M_NULLPTR) { cmdOpts.nsid = NVME_ALL_NAMESPACES; cmdOpts.addr = logBuffer; cmdOpts.dataLen = C_CAST(uint32_t, size); cmdOpts.lid = GET_NVME_LOG_IDENTIFIER; - if (nvme_Get_Log_Page(&deviceList[deviceIter], &cmdOpts) == SUCCESS) + ret = nvme_Get_Log_Page(&deviceList[deviceIter], &cmdOpts); + if (ret == SUCCESS) { if (OUTPUT_MODE_IDENTIFIER == UTIL_OUTPUT_MODE_RAW) { @@ -1140,21 +1225,32 @@ int32_t main(int argc, char *argv[]) } else if (OUTPUT_MODE_IDENTIFIER == UTIL_OUTPUT_MODE_BIN) { - FILE * pLogFile = NULL; - char identifyFileName[OPENSEA_PATH_MAX] = { 0 }; - char * fileNameUsed = &identifyFileName[0]; + secureFileInfo *secureFile = M_NULLPTR; #define SEACHEST_NVME_LOG_NAME_LENGTH 16 - char logName[SEACHEST_NVME_LOG_NAME_LENGTH] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, logName, SEACHEST_NVME_LOG_NAME_LENGTH); snprintf(logName, SEACHEST_NVME_LOG_NAME_LENGTH, "LOG_PAGE_%d", GET_NVME_LOG_IDENTIFIER); - if (SUCCESS == create_And_Open_Log_File(&deviceList[deviceIter], &pLogFile, NULL, \ - logName, "bin", 1, &fileNameUsed)) + if (SUCCESS == create_And_Open_Secure_Log_File_Dev_EZ(&deviceList[deviceIter], &secureFile, NAMING_SERIAL_NUMBER_DATE_TIME, + M_NULLPTR, logName, "bin")) { - fwrite(logBuffer, sizeof(uint8_t), C_CAST(size_t, size), pLogFile); - fflush(pLogFile); - fclose(pLogFile); - if (VERBOSITY_QUIET < toolVerbosity) + if (SEC_FILE_SUCCESS == secure_Write_File(secureFile, logBuffer, uint64_to_sizet(size), sizeof(uint8_t), uint64_to_sizet(size), M_NULLPTR)) { - printf("Created %s with Log Page %" PRIu8" Information\n", fileNameUsed, GET_NVME_LOG_IDENTIFIER); + secure_Flush_File(secureFile); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Created %s with Log Page %" PRIu8 " Information\n", secureFile->fullpath, GET_NVME_LOG_IDENTIFIER); + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to write Log Page Information to file\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + if (SEC_FILE_SUCCESS != secure_Close_File(secureFile)) + { + printf("Error closing file!\n"); } } else @@ -1165,6 +1261,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + free_Secure_File_Info(&secureFile); } else { @@ -1175,6 +1272,14 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; } } + else if (ret == NOT_SUPPORTED) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Log Page %" PRIu8 " is not supported. \n", GET_NVME_LOG_IDENTIFIER); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } else { if (VERBOSITY_QUIET < toolVerbosity) @@ -1183,7 +1288,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free(logBuffer); + safe_free(&logBuffer); } else { @@ -1194,13 +1299,21 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; } } + else if (ret == NOT_SUPPORTED) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Log Page %" PRIu8 " is not supported. \n", GET_NVME_LOG_IDENTIFIER); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } else { if (VERBOSITY_QUIET < toolVerbosity) { printf("Log Page %" PRIu8 " not available at this time. \n", GET_NVME_LOG_IDENTIFIER); } - exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + exitCode = UTIL_EXIT_OPERATION_FAILURE; } } else //Human Readable. @@ -1213,6 +1326,13 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("SMART/Health Information Log not supported\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; default: if (VERBOSITY_QUIET < toolVerbosity) { @@ -1228,6 +1348,13 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error Information Log not supported\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; default: if (VERBOSITY_QUIET < toolVerbosity) { @@ -1243,6 +1370,13 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("FW Slot Information Log not supported\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; default: if (VERBOSITY_QUIET < toolVerbosity) { @@ -1258,6 +1392,13 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Commands Supported and Effects Information Log not supported\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; default: if (VERBOSITY_QUIET < toolVerbosity) { @@ -1273,6 +1414,13 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Device Self-test Information Log not supported\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; default: if (VERBOSITY_QUIET < toolVerbosity) { @@ -1312,18 +1460,18 @@ int32_t main(int argc, char *argv[]) else { uint32_t size = 512; - uint8_t * logBuffer = NULL; + uint8_t * logBuffer = M_NULLPTR; nvmeGetLogPageCmdOpts cmdOpts; uint64_t offset = 0; uint64_t fullSize = 0; - int rtnVal; + eReturnValues rtnVal; nvmeTemetryLogHdr *teleHdr; memset(&cmdOpts, 0, sizeof(nvmeGetLogPageCmdOpts)); - logBuffer = C_CAST(uint8_t*, calloc(size, sizeof(uint8_t))); + logBuffer = C_CAST(uint8_t*, safe_calloc(size, sizeof(uint8_t))); - if (logBuffer != NULL) + if (logBuffer != M_NULLPTR) { cmdOpts.nsid = NVME_ALL_NAMESPACES; cmdOpts.addr = logBuffer; @@ -1396,16 +1544,28 @@ int32_t main(int argc, char *argv[]) } else if (OUTPUT_MODE_IDENTIFIER == UTIL_OUTPUT_MODE_BIN) { - FILE * pLogFile = NULL; - char identifyFileName[OPENSEA_PATH_MAX] = { 0 }; - char * fileNameUsed = &identifyFileName[0]; - char logName[SEACHEST_NVME_LOG_NAME_LENGTH] = { 0 }; + secureFileInfo *secureFile = M_NULLPTR; + DECLARE_ZERO_INIT_ARRAY(char, logName, SEACHEST_NVME_LOG_NAME_LENGTH); snprintf(logName, SEACHEST_NVME_LOG_NAME_LENGTH, "LOG_PAGE_%d", GET_NVME_LOG_IDENTIFIER); - if (SUCCESS == create_And_Open_Log_File(&deviceList[deviceIter], &pLogFile, NULL, \ - logName, "bin", 1, &fileNameUsed)) + if (SUCCESS == create_And_Open_Secure_Log_File_Dev_EZ(&deviceList[deviceIter], &secureFile, NAMING_SERIAL_NUMBER_DATE_TIME, + M_NULLPTR, logName, "bin")) { - fwrite(logBuffer, sizeof(uint8_t), size, pLogFile); - + if (SEC_FILE_SUCCESS == secure_Write_File(secureFile, logBuffer, size, sizeof(uint8_t), size, M_NULLPTR)) + { + secure_Flush_File(secureFile); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Created %s with Log Page %" PRIu8 " Information\n", secureFile->fullpath, GET_NVME_LOG_IDENTIFIER); + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to write Log Page Information to file\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } while (offset < fullSize) { memset(logBuffer, 0, size); @@ -1429,16 +1589,40 @@ int32_t main(int argc, char *argv[]) break; } - fwrite(logBuffer, sizeof(uint8_t), size, pLogFile); + if (SEC_FILE_SUCCESS == secure_Write_File(secureFile, logBuffer, size, sizeof(uint8_t), size, M_NULLPTR)) + { + secure_Flush_File(secureFile); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to write Log Page Information to file\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (SEC_FILE_SUCCESS == secure_Write_File(secureFile, logBuffer, size, sizeof(uint8_t), size, M_NULLPTR)) + { + secure_Flush_File(secureFile); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to write Log Page Information to file\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + if (SEC_FILE_SUCCESS != secure_Close_File(secureFile)) + { + printf("Error closing file!\n"); } - - fflush(pLogFile); - fclose(pLogFile); - - if (VERBOSITY_QUIET < toolVerbosity) { - printf("Created %s with Log Page %d Information\n", fileNameUsed, GET_NVME_LOG_IDENTIFIER); + printf("Created %s with Log Page %d Information\n", secureFile->fullpath, GET_NVME_LOG_IDENTIFIER); } } else @@ -1449,6 +1633,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + free_Secure_File_Info(&secureFile); } else { @@ -1467,7 +1652,7 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free(logBuffer); + safe_free(&logBuffer); } else { @@ -1479,7 +1664,7 @@ int32_t main(int argc, char *argv[]) } } } - + if (NVME_TEMP_STATS_FLAG) { switch (nvme_Print_Temp_Statistics(&deviceList[deviceIter])) @@ -1487,8 +1672,8 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) { printf("Printing Temperature Statistics data is not supported on this drive type.\n"); } @@ -1511,8 +1696,8 @@ int32_t main(int argc, char *argv[]) case SUCCESS: //nothing to print here since if it was successful, the log will be printed to the screen break; - case NOT_SUPPORTED: - if (VERBOSITY_QUIET < toolVerbosity) + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) { printf("Printing PCI Statistics data is not supported on this drive type.\n"); } @@ -1561,6 +1746,32 @@ int32_t main(int argc, char *argv[]) } } + if (SHOW_NVM_POWER_STATES) + { + nvmeSupportedPowerStates ps; + memset(&ps, 0, sizeof(nvmeSupportedPowerStates)); + switch (get_NVMe_Power_States(&deviceList[deviceIter], &ps)) + { + case SUCCESS: + print_NVM_Power_States(&ps); + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Showing NVM power states is not supported on this device\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Could not read NVM power states from the device!\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + //this option must come after --transition power so that these two options can be combined on the command line and produce the correct end result if (CHECK_POWER_FLAG) { @@ -1635,28 +1846,13 @@ int32_t main(int argc, char *argv[]) if (DOWNLOAD_FW_FLAG) { - FILE* firmwareFilePtr = NULL; - bool fileOpenedSuccessfully = true;//assume true in case of activate command - if (DOWNLOAD_FW_MODE != DL_FW_ACTIVATE) + secureFileInfo* fwfile = secure_Open_File(DOWNLOAD_FW_FILENAME_FLAG, "rb", M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (fwfile && fwfile->error == SEC_FILE_SUCCESS) { - //open the file and send the download - if ((firmwareFilePtr = fopen(DOWNLOAD_FW_FILENAME_FLAG, "rb")) == NULL) - { - fileOpenedSuccessfully = false; - } - } - if (DOWNLOAD_FW_MODE == DL_FW_ACTIVATE) - { - //this shouldn't fall into this code path anymore... - fileOpenedSuccessfully = false; - } - if (fileOpenedSuccessfully) - { - size_t firmwareFileSize = get_File_Size(firmwareFilePtr); - uint8_t* firmwareMem = C_CAST(uint8_t*, calloc_aligned(firmwareFileSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t* firmwareMem = C_CAST(uint8_t*, safe_calloc_aligned(fwfile->fileSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (firmwareMem) { - if (firmwareFileSize == fread(firmwareMem, sizeof(uint8_t), firmwareFileSize, firmwareFilePtr)) + if (SEC_FILE_SUCCESS == secure_Read_File(fwfile, firmwareMem, fwfile->fileSize, sizeof(uint8_t), fwfile->fileSize, M_NULLPTR)) { firmwareUpdateData dlOptions; seatimer_t commandTimer; @@ -1664,7 +1860,7 @@ int32_t main(int argc, char *argv[]) memset(&commandTimer, 0, sizeof(seatimer_t)); dlOptions.size = sizeof(firmwareUpdateData); dlOptions.version = FIRMWARE_UPDATE_DATA_VERSION; - dlOptions.dlMode = DOWNLOAD_FW_MODE; + dlOptions.dlMode = C_CAST(eFirmwareUpdateMode, DOWNLOAD_FW_MODE); if (FWDL_SEGMENT_SIZE_FROM_USER) { dlOptions.segmentSize = FWDL_SEGMENT_SIZE_FLAG; @@ -1675,7 +1871,7 @@ int32_t main(int argc, char *argv[]) } dlOptions.ignoreStatusOfFinalSegment = false; dlOptions.firmwareFileMem = firmwareMem; - dlOptions.firmwareMemoryLength = C_CAST(uint32_t, firmwareFileSize);//firmware files shouldn't be larger than a few MBs for a LONG time + dlOptions.firmwareMemoryLength = C_CAST(uint32_t, fwfile->fileSize);//firmware files shouldn't be larger than a few MBs for a LONG time dlOptions.firmwareSlot = FIRMWARE_SLOT_FLAG; start_Timer(&commandTimer); ret = firmware_Download(&deviceList[deviceIter], &dlOptions); @@ -1691,7 +1887,7 @@ int32_t main(int argc, char *argv[]) print_Time(get_Nano_Seconds(commandTimer)); printf("Average time/segment "); print_Time(dlOptions.avgSegmentDlTime); - if (DOWNLOAD_FW_MODE != DL_FW_DEFERRED) + if (ret != POWER_CYCLE_REQUIRED && dlOptions.activateFWTime > 0) { printf("Activate Time "); print_Time(dlOptions.activateFWTime); @@ -1701,7 +1897,7 @@ int32_t main(int argc, char *argv[]) { printf("The Operating system has reported that a power cycle is required to complete the firmware update\n"); } - if (DOWNLOAD_FW_MODE == DL_FW_DEFERRED) + if (DOWNLOAD_FW_MODE == FWDL_UPDATE_MODE_DEFERRED) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1764,11 +1960,19 @@ int32_t main(int argc, char *argv[]) } exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(firmwareMem) + safe_free_aligned(&firmwareMem); } else { perror("failed to allocate memory"); + if (fwfile) + { + if (SEC_FILE_SUCCESS != secure_Close_File(fwfile)) + { + printf("Error attempting to close file!\n"); + } + free_Secure_File_Info(&fwfile); + } exit(255); } } @@ -1776,11 +1980,18 @@ int32_t main(int argc, char *argv[]) { if (VERBOSITY_QUIET < toolVerbosity) { - perror("fopen"); printf("Couldn't open file %s\n", DOWNLOAD_FW_FILENAME_FLAG); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } + if (fwfile) + { + if (SEC_FILE_SUCCESS != secure_Close_File(fwfile)) + { + printf("Error attempting to close file!\n"); + } + free_Secure_File_Info(&fwfile); + } } if (ACTIVATE_DEFERRED_FW_FLAG || SWITCH_FW_FLAG) @@ -1800,7 +2011,7 @@ int32_t main(int argc, char *argv[]) dlOptions.version = FIRMWARE_UPDATE_DATA_VERSION; dlOptions.dlMode = FWDL_UPDATE_MODE_ACTIVATE; dlOptions.segmentSize = 0; - dlOptions.firmwareFileMem = NULL; + dlOptions.firmwareFileMem = M_NULLPTR; dlOptions.firmwareMemoryLength = 0; dlOptions.firmwareSlot = FIRMWARE_SLOT_FLAG; if (SWITCH_FW_FLAG) @@ -1963,7 +2174,7 @@ int32_t main(int argc, char *argv[]) default: break; } - int formatRet = run_NVMe_Format(&deviceList[deviceIter], nvmformatParameters, POLL_FLAG); + eReturnValues formatRet = run_NVMe_Format(&deviceList[deviceIter], nvmformatParameters, POLL_FLAG); switch (formatRet) { case SUCCESS: @@ -2015,9 +2226,9 @@ int32_t main(int argc, char *argv[]) } } - if (PROGRESS_CHAR != NULL) + if (PROGRESS_CHAR != M_NULLPTR) { - int result = UNKNOWN; + eReturnValues result = UNKNOWN; //first take whatever was entered in progressTest and convert it to uppercase to do fewer string comparisons convert_String_To_Upper_Case(progressTest); //do some string comparisons to figure out what we are checking for progress on @@ -2058,7 +2269,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -2107,15 +2318,15 @@ void utility_Usage(bool shortUsage) printf("\tChecking and changing power states:\n"); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, CHECK_POWER_LONG_OPT_STRING); printf("\t%s -d %s --%s 1\n", util_name, deviceHandleExample, TRANSITION_POWER_STATE_LONG_OPT_STRING); - printf("\tPulling the Telemetry log:\n"); + printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, SHOW_NVM_POWER_STATES_LONG_OPT_STRING); + printf("\tPulling the Telemetry log:\n"); printf("\t%s -d %s --%s host\n", util_name, deviceHandleExample, GET_TELEMETRY_LONG_OPT_STRING); printf("\t%s -d %s --%s host, --%s 2 --%s bin\n", util_name, deviceHandleExample, GET_TELEMETRY_LONG_OPT_STRING, TELEMETRY_DATA_AREA_LONG_OPT_STRING, OUTPUT_MODE_LONG_OPT_STRING); - //TODO: other log options/feature options //return codes printf("Return codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options printf("\nUtility Options\n"); @@ -2154,6 +2365,7 @@ void utility_Usage(bool shortUsage) print_Get_Features_Help(shortUsage); print_NVMe_Get_Log_Help(shortUsage); print_NVMe_Get_Tele_Help(shortUsage); + print_Supported_Logs_Help(shortUsage); print_Firmware_Revision_Match_Help(shortUsage); print_pcierr_Help(shortUsage); print_Poll_Help(shortUsage); @@ -2162,6 +2374,7 @@ void utility_Usage(bool shortUsage) print_Output_Mode_Help(shortUsage); print_NVMe_Temp_Stats_Help(shortUsage); print_NVMe_Pci_Stats_Help(shortUsage); + print_Show_NVM_Power_States_Help(shortUsage); print_Show_Supported_Formats_Help(shortUsage); //data destructive commands diff --git a/utils/C/openSeaChest/openSeaChest_PassthroughTest.c b/utils/C/openSeaChest/openSeaChest_PassthroughTest.c index 44afa268..95489464 100644 --- a/utils/C/openSeaChest/openSeaChest_PassthroughTest.c +++ b/utils/C/openSeaChest/openSeaChest_PassthroughTest.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2019-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2019-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,16 +15,17 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#include "getopt.h" -#elif defined (_WIN32) +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "sleep.h" +#include "math_utils.h" +#include "pattern_utils.h" + #include "getopt.h" -#else -#error "OS Not Defined or known" -#endif #include "EULA.h" #include "openseachest_util_options.h" #include "operations.h" @@ -33,7 +35,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_PassthroughTest"; -const char *buildVersion = "1.3.3"; +const char *buildVersion = "1.4.1"; //////////////////////////// // functions to declare // @@ -62,17 +64,17 @@ typedef struct _passthroughTestParams bool noMultiSectorPIOTest; bool noReturnResponseInfoTest; bool nocheckConditionTest; - + }passthroughTestParams, *ptrPassthroughTestParams; -int perform_Passthrough_Test(ptrPassthroughTestParams inputs); +eReturnValues perform_Passthrough_Test(ptrPassthroughTestParams inputs); -#define HACK_COLOR BLUE -#define LIKELY_HACK_COLOR CYAN -#define WARNING_COLOR YELLOW -#define ERROR_COLOR RED -#define NOTE_COLOR MAGENTA -#define HEADING_COLOR GREEN +#define HACK_COLOR CONSOLE_COLOR_BLUE +#define LIKELY_HACK_COLOR CONSOLE_COLOR_CYAN +#define WARNING_COLOR CONSOLE_COLOR_YELLOW +#define ERROR_COLOR CONSOLE_COLOR_RED +#define NOTE_COLOR CONSOLE_COLOR_MAGENTA +#define HEADING_COLOR CONSOLE_COLOR_GREEN //run the passthrough test #define RUN_PASSTHROUGH_TEST_FLAG passthroughTest @@ -84,7 +86,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs); #define PT_DRIVE_HINT passthroughDriveTypeHint #define PT_DRIVE_HINT_VAR int PT_DRIVE_HINT = -1; #define PT_DRIVE_HINT_LONG_OPT_STRING "ptDriveHint" -#define PT_DRIVE_HINT_LONG_OPT { PT_DRIVE_HINT_LONG_OPT_STRING, required_argument, NULL, 0 } +#define PT_DRIVE_HINT_LONG_OPT { PT_DRIVE_HINT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } static void print_Drive_Type_Hint_Help(bool shortHelp) { @@ -102,13 +104,13 @@ static void print_Drive_Type_Hint_Help(bool shortHelp) #define PT_PTTYPE_HINT passthroughTypeHint #define PT_PTTYPE_HINT_VAR int PT_PTTYPE_HINT = -1; #define PT_PTTYPE_HINT_LONG_OPT_STRING "ptTypeHint" -#define PT_PTTYPE_HINT_LONG_OPT { PT_PTTYPE_HINT_LONG_OPT_STRING, required_argument, NULL, 0 } +#define PT_PTTYPE_HINT_LONG_OPT { PT_PTTYPE_HINT_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } static void print_Passthrough_Type_Hint_Help(bool shortHelp) { printf("\t--%s [sat | legacyATA]\n", PT_PTTYPE_HINT_LONG_OPT_STRING); if (!shortHelp) - { + { printf("\t\tAdd this option if the device being tested is likely to support one of\n"); printf("\t\tthe supported passthrough types. This hints to the software to perform\n"); printf("\t\tadditional testing for these passthroughs if no other support is apparent.\n"); @@ -132,7 +134,7 @@ static void print_Disable_PT_Testing_Help(bool shortHelp) { printf("\t--%s\n", DISABLE_PT_TESTING_LONG_OPT_STRING); if (!shortHelp) - { + { printf("\t\tDisables all ATA passthrough testing. Device will only be tested with SCSI commands from\n"); printf("\t\tSPC and SBC specifications.\n\n"); } @@ -147,7 +149,7 @@ static void print_Enable_Legacy_ATA_PT_Testing_Help(bool shortHelp) { printf("\t--%s\n", ENABLE_LEGACY_ATA_PT_TESTING_LONG_OPT_STRING); if (!shortHelp) - { + { printf("\t\tAdd this option to the command line to allow sending legacy passthrough CDBs from\n"); printf("\t\told USB adapters or drivers. By default these are off since these operation codes\n"); printf("\t\tmay perform unintended actions on devices that don't actually support passthrough.\n"); @@ -170,7 +172,7 @@ static void print_Enable_Legacy_ATA_PT_Testing_Help(bool shortHelp) int TEST_RETURN_RESPONSE_NO_TDIR = 0; //Add more here if we run into other commands that hang some devices #define ENABLE_HANG_COMMANDS_TEST_LONG_OPT_STRING "enableHangCmdsTest" -#define ENABLE_HANG_COMMANDS_TEST_LONG_OPT { ENABLE_HANG_COMMANDS_TEST_LONG_OPT_STRING, required_argument, NULL, 0 } +#define ENABLE_HANG_COMMANDS_TEST_LONG_OPT { ENABLE_HANG_COMMANDS_TEST_LONG_OPT_STRING, required_argument, M_NULLPTR, 0 } static void print_Enable_Hang_Commands_Test_Help(bool shortHelp) { @@ -247,14 +249,14 @@ static void print_Run_Passthrough_Test_Help(bool shortHelp) //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -292,7 +294,7 @@ int32_t main(int argc, char *argv[]) #endif LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -370,9 +372,9 @@ int32_t main(int argc, char *argv[]) { case 0: //parse long options that have no short option and required arguments here - if (strncmp(longopts[optionIndex].name, PT_DRIVE_HINT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(PT_DRIVE_HINT_LONG_OPT_STRING))) == 0) + if (strcmp(longopts[optionIndex].name, PT_DRIVE_HINT_LONG_OPT_STRING) == 0) { - if (strcmp(optarg, "ata") == 0 || strcmp(optarg, "ATA") == 0 || strcmp(optarg, "sata") == 0 || strcmp(optarg, "SATA") == 0 || strcmp(optarg, "pata") == 0 || strcmp(optarg, "PATA") == 0 || strcmp(optarg, "ide") == 0 || strcmp(optarg, "IDE") == 0 ) + if (strcmp(optarg, "ata") == 0 || strcmp(optarg, "ATA") == 0 || strcmp(optarg, "sata") == 0 || strcmp(optarg, "SATA") == 0 || strcmp(optarg, "pata") == 0 || strcmp(optarg, "PATA") == 0 || strcmp(optarg, "ide") == 0 || strcmp(optarg, "IDE") == 0) { PT_DRIVE_HINT = ATA_DRIVE; } @@ -386,7 +388,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, PT_PTTYPE_HINT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(PT_PTTYPE_HINT_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, PT_PTTYPE_HINT_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "sat") == 0 || strcmp(optarg, "SAT") == 0) { @@ -404,7 +406,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ENABLE_HANG_COMMANDS_TEST_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ENABLE_HANG_COMMANDS_TEST_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ENABLE_HANG_COMMANDS_TEST_LONG_OPT_STRING) == 0) { ENABLE_HANG_COMMANDS_TEST = 1; if (strcmp(optarg, "all") == 0) @@ -431,22 +433,22 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -515,9 +517,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -554,7 +557,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -651,7 +654,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -707,6 +710,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -716,7 +721,7 @@ int32_t main(int argc, char *argv[]) { set_Console_Colors(true, ERROR_COLOR); printf("\nError: Only one force flag can be used at a time.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } @@ -739,7 +744,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -787,7 +792,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -835,11 +840,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -863,7 +868,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -875,7 +880,7 @@ int32_t main(int argc, char *argv[]) printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); - if(ret == PERMISSION_DENIED || !is_Running_Elevated()) + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) { exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); } @@ -905,7 +910,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -930,7 +935,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -969,6 +974,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1049,33 +1063,33 @@ int32_t main(int argc, char *argv[]) if (PT_DRIVE_HINT > 0) { params.suspectedDriveTypeProvidedByUser = true; - params.suspectedDriveType = PT_DRIVE_HINT; + params.suspectedDriveType = C_CAST(eDriveType, PT_DRIVE_HINT); } if (PT_PTTYPE_HINT > 0) { params.suspectedPassthroughProvidedByUser = true; //TODO: Handle value of 50 meaning test all legacy methods! - params.suspectedPassthroughType = PT_PTTYPE_HINT; + params.suspectedPassthroughType = C_CAST(ePassthroughType, PT_PTTYPE_HINT); } perform_Passthrough_Test(¶ms); - + } //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } -static int return_Response_Extend_Bit_Test(tDevice *device) +static eReturnValues return_Response_Extend_Bit_Test(tDevice *device) { - int ret = NOT_SUPPORTED; + eReturnValues ret = NOT_SUPPORTED; //Do additional command testing to check if the extend bit is reported correctly or not. //This obviously requires a 48bit drive and support for a command such as reading the native max LBA if (device->drive_info.ata_Options.fourtyEightBitAddressFeatureSetSupported) { uint64_t nativeMaxLBA = 0; - int nativeMaxRet = 0; + eReturnValues nativeMaxRet = 0; bool commandIssued = true; //check HPA or AMAC support as those are preferred commands to be used. //The values that are returned should be greater than or equal to the current maxLBA of the drive. @@ -1109,7 +1123,7 @@ static int return_Response_Extend_Bit_Test(tDevice *device) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RSIE\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -1136,7 +1150,7 @@ static int return_Response_Extend_Bit_Test(tDevice *device) printf(" This means only 28bit commands will get full results. 48bit commands will be partial\n"); set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: PARTRTFR\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.partialRTFRs = true; } } @@ -1163,7 +1177,7 @@ static int return_Response_Extend_Bit_Test(tDevice *device) printf(" This means only 28bit commands will get full results. 48bit commands will be partial\n"); set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: PARTRTFR\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.partialRTFRs = true; } } @@ -1172,7 +1186,7 @@ static int return_Response_Extend_Bit_Test(tDevice *device) //Something went really wrong set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Command failure while trying to perform RTFR return response info test.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return FAILURE; } } @@ -1183,17 +1197,17 @@ static int return_Response_Extend_Bit_Test(tDevice *device) printf("NOTE: This device doesn't support 48bit commands. Cannot test for proper extend bit in\n"); printf(" return response information test. It is strongly recommended that this adapter is retested\n"); printf(" with a device that supports 48bit commands so that this can be tested properly\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } return ret; } static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t logAddress, uint32_t logSize) { - uint8_t *log = C_CAST(uint8_t*, calloc_aligned(logSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *log = C_CAST(uint8_t*, safe_calloc_aligned(logSize, sizeof(uint8_t), device->os_info.minimumAlignment)); if (log) { - int cmdResult = SUCCESS; + eReturnValues cmdResult = SUCCESS; fill_Random_Pattern_In_Buffer(log, logSize); if (gpl) { @@ -1207,7 +1221,7 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l if (cmdResult == SUCCESS) { //now we need to read and compare if the pattern changed! - uint8_t *logR = C_CAST(uint8_t*, calloc_aligned(logSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *logR = C_CAST(uint8_t*, safe_calloc_aligned(logSize, sizeof(uint8_t), device->os_info.minimumAlignment)); if (logR) { if (gpl) @@ -1227,7 +1241,7 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: MMPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -1241,7 +1255,7 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l device->drive_info.passThroughHacks.ataPTHacks.multiSectorPIOWithMultipleMode = false; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; } else @@ -1270,7 +1284,7 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; } } @@ -1292,13 +1306,13 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l { cmdResult = ata_SMART_Write_Log(device, logAddress, log, logSize, false); } - safe_Free_aligned(logR) + safe_Free_aligned(C_CAST(void**, &logR)); } else { set_Console_Colors(true, ERROR_COLOR); printf("FATAL ERROR: Unable to allocate enough memory to finish multi-sector PIO test!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } //clear the log back to zeros if necessary } @@ -1311,7 +1325,7 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l { device->drive_info.passThroughHacks.ataPTHacks.multiSectorPIOWithMultipleMode = true; //recursively call this function and try again - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); multi_Sector_PIO_Test_With_Logs(device, gpl, logAddress, logSize); } else @@ -1329,11 +1343,11 @@ static void multi_Sector_PIO_Test_With_Logs(tDevice *device, bool gpl, uint8_t l { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; } } - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); } } @@ -1348,7 +1362,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma { printf("Checking multi-sector PIO command support\n"); bool foundMultiSectorLogPage = false; - uint8_t logDir[512] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, logDir, 512); //Attempt read log commands first since they aren't touching media if (device->drive_info.ata_Options.generalPurposeLoggingSupported) { @@ -1368,7 +1382,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma if (logSize > 0) { uint32_t allocedLogSize = C_CAST(uint32_t, logSize) * UINT32_C(512); - uint8_t *log = C_CAST(uint8_t *, calloc_aligned(allocedLogSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *log = C_CAST(uint8_t *, safe_calloc_aligned(allocedLogSize, sizeof(uint8_t), device->os_info.minimumAlignment)); if (log) { if (SUCCESS == ata_Read_Log_Ext(device, logAddress, 0, log, allocedLogSize, false, 0)) @@ -1376,15 +1390,15 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma //now check if it's empty so we don't overwrite any data in it. if (is_Empty(log, allocedLogSize)) { - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); multi_Sector_PIO_Test_With_Logs(device, true, C_CAST(uint8_t, iter / 2), allocedLogSize); break; } - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); } else { - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); printf("WARNING: Failed to read multi-sector log with PIO commands. Likely a chip not compliant with multisector PIO commands\n"); if (!device->drive_info.passThroughHacks.ataPTHacks.multiSectorPIOWithMultipleMode && M_Byte0(device->drive_info.IdentifyData.ata.Word047) > 0) { @@ -1415,7 +1429,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma device->drive_info.passThroughHacks.ataPTHacks.multiSectorPIOWithMultipleMode = false; set_Console_Colors(true, LIKELY_HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; } } @@ -1425,7 +1439,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma printf("Unable to perform test of multi-sector PIO commands\n"); set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; break; } @@ -1433,7 +1447,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; break; } @@ -1462,7 +1476,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma if (logSize > 0) { uint32_t allocedLogSize = C_CAST(uint32_t, logSize) * UINT32_C(512); - uint8_t *log = C_CAST(uint8_t *, calloc_aligned(allocedLogSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *log = C_CAST(uint8_t *, safe_calloc_aligned(allocedLogSize, sizeof(uint8_t), device->os_info.minimumAlignment)); if (log) { if (SUCCESS == ata_SMART_Read_Log(device, logAddress, log, allocedLogSize)) @@ -1470,18 +1484,18 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma //now check if it's empty so we don't overwrite any data in it. if (is_Empty(log, allocedLogSize)) { - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); multi_Sector_PIO_Test_With_Logs(device, false, C_CAST(uint8_t, iter / 2), allocedLogSize); break; } - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); } else { - safe_Free_aligned(log) + safe_Free_aligned(C_CAST(void**, &log)); set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Failed to read multi-sector log with PIO commands. Likely a chip not compliant with multisector PIO commands\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); if (!device->drive_info.passThroughHacks.ataPTHacks.multiSectorPIOWithMultipleMode && M_Byte1(device->drive_info.IdentifyData.ata.Word047) == 0x80 && M_Byte0(device->drive_info.IdentifyData.ata.Word047) > 0) { printf("Retrying after changing the multiple mode.\n"); @@ -1507,7 +1521,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma printf("Unable to perform test of multi-sector PIO commands\n"); set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; break; } @@ -1515,7 +1529,7 @@ static void multi_Sector_PIO_Test(tDevice *device, bool smartSupported, bool sma { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; break; } @@ -1539,7 +1553,7 @@ static void sat_DMA_UDMA_Protocol_Test(tDevice *device, M_ATTR_UNUSED bool smart uint64_t lba = 0; uint16_t sectors = 1; uint32_t dataSize = device->drive_info.bridge_info.childDeviceBlockSize * sectors; - uint8_t *ptrData = C_CAST(uint8_t *, calloc_aligned(dataSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *ptrData = C_CAST(uint8_t *, safe_calloc_aligned(dataSize, sizeof(uint8_t), device->os_info.minimumAlignment)); if (ptrData) { bool use48 = device->drive_info.ata_Options.fourtyEightBitAddressFeatureSetSupported; @@ -1548,18 +1562,18 @@ static void sat_DMA_UDMA_Protocol_Test(tDevice *device, M_ATTR_UNUSED bool smart use48 = false; } device->drive_info.ata_Options.dmaMode = ATA_DMA_MODE_DMA; - int dmaReadRet = ata_Read_DMA(device, lba, ptrData, sectors, dataSize, use48); + eReturnValues dmaReadRet = ata_Read_DMA(device, lba, ptrData, sectors, dataSize, use48); device->drive_info.ata_Options.dmaMode = ATA_DMA_MODE_UDMA; - int udmaReadRet = ata_Read_DMA(device, lba, ptrData, sectors, dataSize, use48); + eReturnValues udmaReadRet = ata_Read_DMA(device, lba, ptrData, sectors, dataSize, use48); if (dmaReadRet != SUCCESS && udmaReadRet != SUCCESS) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NDMA\n");//Cannot issue any DMA mode commands. - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); set_Console_Colors(true, ERROR_COLOR); printf("ERROR: No possible way to issue a DMA mode command on this device.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.ata_Options.dmaMode = ATA_DMA_MODE_NO_DMA; } else @@ -1568,34 +1582,34 @@ static void sat_DMA_UDMA_Protocol_Test(tDevice *device, M_ATTR_UNUSED bool smart { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: FDMA\n");//force using DMA mode instead of UDMA - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.ata_Options.dmaMode = ATA_DMA_MODE_DMA; } else if (udmaReadRet == SUCCESS && dmaReadRet != SUCCESS) { set_Console_Colors(true, NOTE_COLOR); printf("NOTE: Device only supports UDMA mode for passthrough. This is the default for the tool, but may be an issue for some other tools.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.ata_Options.dmaMode = ATA_DMA_MODE_UDMA; } else if (udmaReadRet == SUCCESS && dmaReadRet == SUCCESS) { printf("Both UDMA and DMA protocols are supported.\n"); - } + } else { set_Console_Colors(true, ERROR_COLOR); printf("FATAL ERROR: You shouldn't be seeing this message. Something went horribly wrong\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } - safe_Free_aligned(ptrData) + safe_Free_aligned(C_CAST(void**, &ptrData)); } else { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Unable to allocate memory for DMA/UDMA protocol test\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } return; } @@ -1606,8 +1620,8 @@ static void check_Condition_Bit_Test(tDevice *device, bool smartSupported, bool printf("Testing for check condition bit support on any command\n"); device->drive_info.passThroughHacks.ataPTHacks.alwaysCheckConditionAvailable = true; //try identify first...if this doesn't even work, then we know this doesn't work - uint8_t identifyData[512] = { 0 }; - int satRet = ata_Identify(device, identifyData, 512); + DECLARE_ZERO_INIT_ARRAY(uint8_t, identifyData, 512); + eReturnValues satRet = ata_Identify(device, identifyData, 512); if ((SUCCESS == satRet || WARN_INVALID_CHECKSUM == satRet) && !is_Empty(identifyData, 512)) { bool testedGPL = false, testedSMART = false; @@ -1624,11 +1638,11 @@ static void check_Condition_Bit_Test(tDevice *device, bool smartSupported, bool { //SMART is available. //Try SMART read data - uint8_t *smartData = C_CAST(uint8_t*, calloc_aligned(512, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *smartData = C_CAST(uint8_t*, safe_calloc_aligned(512, sizeof(uint8_t), device->os_info.minimumAlignment)); memset(&device->drive_info.lastCommandRTFRs, 0, sizeof(ataReturnTFRs)); if (smartData) { - int smartRet = ata_SMART_Read_Data(device, smartData, 512); + eReturnValues smartRet = ata_SMART_Read_Data(device, smartData, 512); if (SUCCESS == smartRet || WARN_INVALID_CHECKSUM == smartRet) { //Make sure the registers show successful completion and not zeros @@ -1653,7 +1667,7 @@ static void check_Condition_Bit_Test(tDevice *device, bool smartSupported, bool } } //Lastly, try a SMART return status command. This SHOULD - safe_Free_aligned(smartData) + safe_Free_aligned(C_CAST(void**, &smartData)); testedSMART = true; } } @@ -1667,7 +1681,7 @@ static void check_Condition_Bit_Test(tDevice *device, bool smartSupported, bool { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: CHK\n");//check condition bit is always supported properly - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -1683,13 +1697,13 @@ static void check_Condition_Bit_Test(tDevice *device, bool smartSupported, bool { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: CHKND\n");//check condition bit is supported for non-data commands only - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: CHKE\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.checkConditionEmpty = true; } } @@ -1709,14 +1723,14 @@ static void check_Condition_Bit_Test(tDevice *device, bool smartSupported, bool { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: CHKND\n");//check condition bit is supported for non-data commands only - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } else { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NCHK\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.ataPTHacks.disableCheckCondition = true; } } @@ -1734,7 +1748,7 @@ static void return_Response_Info_Test(tDevice *device, M_ATTR_UNUSED bool smartS set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RS\n");//returnResponseInfoSupported printf("HACK FOUND: RSTD\n");//returnResponseInfoNeedsTDIR - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (testWithoutTDirAllowed) { @@ -1745,8 +1759,8 @@ static void return_Response_Info_Test(tDevice *device, M_ATTR_UNUSED bool smartS device->drive_info.passThroughHacks.ataPTHacks.returnResponseInfoSupported = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RS\n");//returnResponseInfoSupported - set_Console_Colors(true, DEFAULT); - + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + } } if (device->drive_info.passThroughHacks.ataPTHacks.returnResponseInfoSupported) @@ -1772,7 +1786,7 @@ typedef struct _rawDesignator typedef struct _scsiDevInfo { //inquiry data - struct + struct { char vendorId[T10_VENDOR_ID_LEN + 1]; char productId[INQ_DATA_PRODUCT_ID_LEN + 1]; @@ -1785,7 +1799,7 @@ typedef struct _scsiDevInfo bool satVersionDescriptorFound; }inquiryData; //read capacity data - zeros mean we couldn't read one of these pieces of information. - struct + struct { uint32_t rc10MaxLBA; uint32_t rc10blockSize; @@ -1794,7 +1808,7 @@ typedef struct _scsiDevInfo uint32_t rc16physBlockSize; }readCapData; //vpd page data - struct + struct { bool gotUnitSNVPDPage; char unitSN[255]; @@ -1803,7 +1817,7 @@ typedef struct _scsiDevInfo rawDesignator designators[8]; bool gotSATVPDPage; bool gotPowerConditionsVPDPage; - struct + struct { bool standby_z; bool standby_y; @@ -1819,7 +1833,7 @@ typedef struct _scsiDevInfo bool gotExInquiryVPDPage; uint16_t vpdDSTTimeMinutes;//ext dst from VPD page. If zero, either not reported on this page, or device just doesn't do this translation bool gotBlockCharacteristicsVPDPage; - struct + struct { uint16_t rotationRate; uint8_t productType; @@ -1827,7 +1841,7 @@ typedef struct _scsiDevInfo uint8_t zonedCapabilities; }blockCharacteristicsData; bool gotBlockLimitsVPDPage; - struct + struct { uint32_t maximumXferLen; uint32_t optimalXferLen; @@ -1838,10 +1852,10 @@ typedef struct _scsiDevInfo //TODO: based on reported VPD pages (mode page policy and/or feature sets, etc), create a list of mode pages that are expected to be supported for the mode page test. }vpdData; //Log Page data - struct + struct { bool readErrorsFound; - struct + struct { union { uint32_t readRecoveryAttempts;//ATA @@ -1853,13 +1867,13 @@ typedef struct _scsiDevInfo }; }readErrorData; bool gotTemperature; - struct + struct { uint8_t temperature; uint8_t referenceTemperature; }temperatureData; bool gotStartStop; - struct + struct { union { uint32_t headLoadEvents; @@ -1871,28 +1885,28 @@ typedef struct _scsiDevInfo }; }startStopData; bool gotSelfTestData; - struct + struct { uint32_t totalSelfTestEntries;//Only doing this because it is more complicated to compare the fields with ATA and is not really worth it right now - TJE }selfTestData; bool gotSolidStateData; - struct + struct { uint8_t percentUsedIndicator; }solidStateData; bool gotBackgroundScan; - struct + struct { uint64_t accumulatedPowerOnMinutes;//60 * ATA Power on hours statistic }backgroundData; bool gotZonedStatistics; - struct + struct { //TODO: zoned statistics uint8_t reserved; }zonedData; bool gotGeneralStatistics; - struct + struct { uint64_t numberOfReadCommands; uint64_t numberOfWriteCommands; @@ -1900,12 +1914,12 @@ typedef struct _scsiDevInfo uint64_t numberOfLogicalBlocksTransmitted; }generalStatisticsData; bool gotPendingDefects; - struct + struct { uint32_t pendingDefectsCount; }pendingDefectsData; bool gotInformationalExceptions; - struct + struct { uint8_t asc; uint8_t ascq; @@ -1917,32 +1931,32 @@ typedef struct _scsiDevInfo struct { bool gotControlPage; - struct + struct { bool d_sense; uint16_t extDSTCompletionTimeSeconds;//Seconds //TODO: busy timeout period??? }controlData; bool gotControlExtensionPage;//not in NVMe - struct + struct { uint8_t maxSenseDataLength;//what is it currently set to here...can also be changed here. }controlExtData; bool gotReadWriteErrorRecoveryPage; - struct + struct { bool awre;//true for everything today. Possibly false if it is an old drive....can tell by checking defaults instead of current values. bool arre;//false for ATA, true for NVMe uint16_t recoveryTimeLimit;//0 for all ATA devices according to SAT. NVMe will set this to value of a feature. }rwErrRecData; bool gotCachingPage; - struct + struct { bool wce; bool dra;//not on NVMe ever. }cachingData; bool gotInformationalExceptionsControlPage; - struct + struct { uint8_t mrie; bool ewasc; @@ -1950,7 +1964,7 @@ typedef struct _scsiDevInfo bool perf; }infoExcepData; bool gotRigidDiskPage; - struct + struct { //Storing everything from this page for now. uint32_t numberOfCylinders; @@ -1964,7 +1978,7 @@ typedef struct _scsiDevInfo uint16_t mediumRotationRate; }rigidDiskData; bool gotPowerConditionControlPage;//StdSCSI page - struct + struct { uint8_t pageLength;//to help detect legacy devices since this used to be a shorter page bool standbyY; @@ -1980,7 +1994,7 @@ typedef struct _scsiDevInfo uint32_t standbyYTimer; }powerConditionCtrlData; bool gotPataControlPage;//ATA specific for PATA devices. - struct + struct { bool mwd2; bool mwd1; @@ -1996,7 +2010,7 @@ typedef struct _scsiDevInfo bool udma0; }pataCtrlData; bool gotATAPowerConditionPage;//ATA specific page for APM - struct + struct { bool apmp; uint8_t apmValue; @@ -2012,9 +2026,9 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("\n=========================\n"); printf("Checking VPD page support\n"); printf("=========================\n"); - set_Console_Colors(true, DEFAULT); - - uint8_t supportedPages[36] = { 0 }; + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + + DECLARE_ZERO_INIT_ARRAY(uint8_t, supportedPages, 36); uint8_t dummiedPageCount = 0; bool dummiedPages = false; if (SUCCESS != scsi_Inquiry(device, supportedPages, 30, SUPPORTED_VPD_PAGES, true, false)) @@ -2025,7 +2039,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf(" VPD pages communicate other device capabilities\n"); printf(" and limits which are useful to the host.\n"); printf("Will dummy up support to see if any pages are supported that are useful.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); memset(supportedPages, 0, 36); uint16_t offset = 4;//start of pages to dummy up //in here we will set up a fake supported VPD pages buffer so that we try to read the unit serial number page, the SAT page, and device identification page @@ -2079,15 +2093,15 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Supported VPD pages length seems suspiciously large!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } uint16_t pagesread = 0; //TODO: validate peripheral qualifier and peripheral device type on every page with std inquiry data - for (uint32_t vpdIter = 4; vpdIter < C_CAST(uint32_t,(supportedVPDPagesLength + 4)) && vpdIter < INQ_RETURN_DATA_LENGTH; vpdIter++) + for (uint32_t vpdIter = 4; vpdIter < C_CAST(uint32_t, (supportedVPDPagesLength + 4)) && vpdIter < INQ_RETURN_DATA_LENGTH; vpdIter++) { bool genericVPDPageReadOutput = true; bool readVPDPage = false; - uint8_t *pageToRead = C_CAST(uint8_t*, calloc_aligned(4, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *pageToRead = C_CAST(uint8_t*, safe_calloc_aligned(4, sizeof(uint8_t), device->os_info.minimumAlignment)); uint16_t vpdPageLength = 0; printf("\tFound page %" PRIX8 "h\n", supportedPages[vpdIter]); @@ -2107,7 +2121,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Expected page %" PRIX8 "h, but got %" PRIX8 "h\n", supportedPages[vpdIter], pageToRead[1]); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2120,14 +2134,14 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Failed to read page %" PRIX8 "h. Was reported as supported, but cannot be read.\n", supportedPages[vpdIter]); printf(" Attempted to read %" PRIu16 " bytes as reported by device.\n", vpdPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } else { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Unable to allocate memory to read %" PRIu16 "B of page %" PRIX8 "h\n", vpdPageLength, supportedPages[vpdIter]); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } else if (!dummiedPages) @@ -2135,7 +2149,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Failed to read page %" PRIX8 "h. Was reported as supported, but cannot be read.\n", supportedPages[vpdIter]); printf(" Attempted to read only first 4 bytes to determine full VPD page size as spec allows.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } switch (supportedPages[vpdIter]) { @@ -2150,43 +2164,43 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: UNA\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.unitSNAvailable = true; } - char *unitSerialNumber = C_CAST(char *, calloc(vpdPageLength + 1, sizeof(char))); //add 1 for NULL terminator + char *unitSerialNumber = C_CAST(char *, safe_calloc(vpdPageLength + 1, sizeof(char))); //add 1 for M_NULLPTR terminator if (unitSerialNumber) { scsiDevInfo->vpdData.gotUnitSNVPDPage = true; memcpy(unitSerialNumber, &pageToRead[4], vpdPageLength); for (uint16_t iter = 0; iter < vpdPageLength && iter < UINT16_MAX; ++iter) { - if (!is_ASCII(unitSerialNumber[iter]) || !isprint(unitSerialNumber[iter])) + if (!safe_isascii(unitSerialNumber[iter]) || !safe_isprint(unitSerialNumber[iter])) { unitSerialNumber[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Unit Serial Number contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } - if (strlen(unitSerialNumber) == 0) + if (safe_strlen(unitSerialNumber) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Unit Serial Number is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { genericVPDPageReadOutput = false; printf("\tGot Unit Serial Number as %s\n", unitSerialNumber); - memcpy(&scsiDevInfo->vpdData.unitSN, unitSerialNumber, M_Min(255, strlen(unitSerialNumber))); + memcpy(&scsiDevInfo->vpdData.unitSN, unitSerialNumber, M_Min(255, safe_strlen(unitSerialNumber))); } - safe_Free(unitSerialNumber); + safe_free(&unitSerialNumber); } else { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Unable to allocate %" PRIu16 " Bytes for the serial number\n", vpdPageLength + 1); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } break; @@ -2222,13 +2236,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) switch (codeSet) { case 1://binary values - break; + break; case 2://ASCII printable characters - isASCII = true; - break; + isASCII = true; + break; case 3://UTF-8 codes - isUTF8 = true; - break; + isUTF8 = true; + break; case 0://reserved default://reserved break; @@ -2347,7 +2361,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) case 3://reserved set_Console_Colors(true, WARNING_COLOR); printf("\t\t\tWARNING: Reserved association\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); break; } switch (designatorType) @@ -2362,22 +2376,22 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Code set does not mark this as ASCII! This should be ASCII data!!!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } { - char desVendorID[9] = { 0 }; - char *vendorSpecificID = NULL; + DECLARE_ZERO_INIT_ARRAY(char, desVendorID, 9); + char *vendorSpecificID = M_NULLPTR; memcpy(desVendorID, &pageToRead[designatorOffset], 8); printf("\t\t\t T10 Vendor ID: %s\n", desVendorID); if (designatorLength > 8) { - vendorSpecificID = C_CAST(char*, calloc(designatorLength - 8 + 1, sizeof(char))); + vendorSpecificID = C_CAST(char*, safe_calloc(designatorLength - 8 + 1, sizeof(char))); if (vendorSpecificID) { memcpy(vendorSpecificID, &pageToRead[designatorOffset + 8], designatorLength - 8); //TODO: validate that all characters are printable printf("\t\t\t Vendor Specific ID: %s\n", vendorSpecificID); - safe_Free(vendorSpecificID); + safe_free(&vendorSpecificID); } } else @@ -2385,7 +2399,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) set_Console_Colors(true, WARNING_COLOR); printf("WARNING: T10 Vendor ID based designator is missing vendor specific identifier!!!\n"); printf("Recommended method from SPC is to concatenate Product ID and Product Serial number\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } break; @@ -2401,13 +2415,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("\t\t\t IEEE Company ID: "); for (uint32_t ieeeVIDOffset = designatorOffset; ieeeVIDOffset < C_CAST(uint32_t, (designatorOffset + 3)); ++ieeeVIDOffset) { - printf("%02" PRIX8 , pageToRead[ieeeVIDOffset]); + printf("%02" PRIX8, pageToRead[ieeeVIDOffset]); } printf("\n"); printf("\t\t\t Vendor Specific Extension Identifier: "); for (uint32_t vuExtIDOffset = designatorOffset + 3; vuExtIDOffset < C_CAST(uint32_t, (designatorOffset + 8)); ++vuExtIDOffset) { - printf("%02" PRIX8 , pageToRead[vuExtIDOffset]); + printf("%02" PRIX8, pageToRead[vuExtIDOffset]); } printf("\n"); break; @@ -2416,19 +2430,19 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("\t\t\t IEEE Company ID: "); for (uint32_t ieeeVIDOffset = designatorOffset; ieeeVIDOffset < C_CAST(uint32_t, (designatorOffset + 3)); ++ieeeVIDOffset) { - printf("%02" PRIX8 , pageToRead[ieeeVIDOffset]); + printf("%02" PRIX8, pageToRead[ieeeVIDOffset]); } printf("\n"); printf("\t\t\t Vendor Specific Extension Identifier: "); for (uint32_t vuExtIDOffset = designatorOffset + 3; vuExtIDOffset < C_CAST(uint32_t, (designatorOffset + 8)); ++vuExtIDOffset) { - printf("%02" PRIX8 , pageToRead[vuExtIDOffset]); + printf("%02" PRIX8, pageToRead[vuExtIDOffset]); } printf("\n"); printf("\t\t\t Directory ID: "); for (uint32_t dIDOffset = designatorOffset + 8; dIDOffset < C_CAST(uint32_t, (designatorOffset + 12)); ++dIDOffset) { - printf("%02" PRIX8 , pageToRead[dIDOffset]); + printf("%02" PRIX8, pageToRead[dIDOffset]); } printf("\n"); break; @@ -2437,19 +2451,19 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("\t\t\t Identifier Extension: "); for (uint32_t idExtOffset = designatorOffset; idExtOffset < C_CAST(uint32_t, (designatorOffset + 8)); ++idExtOffset) { - printf("%02" PRIX8 , pageToRead[idExtOffset]); + printf("%02" PRIX8, pageToRead[idExtOffset]); } printf("\n"); printf("\t\t\t IEEE Company ID: "); for (uint32_t ieeeVIDOffset = designatorOffset + 8; ieeeVIDOffset < C_CAST(uint32_t, (designatorOffset + 11)); ++ieeeVIDOffset) { - printf("%02" PRIX8 , pageToRead[ieeeVIDOffset]); + printf("%02" PRIX8, pageToRead[ieeeVIDOffset]); } printf("\n"); printf("\t\t\t Vendor Specific Extension Identifier: "); for (uint32_t vuExtIDOffset = designatorOffset + 11; vuExtIDOffset < C_CAST(uint32_t, (designatorOffset + 16)); ++vuExtIDOffset) { - printf("%02" PRIX8 , pageToRead[vuExtIDOffset]); + printf("%02" PRIX8, pageToRead[vuExtIDOffset]); } printf("\n"); break; @@ -2459,7 +2473,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) //print it out in hex for (uint32_t euiOffset = designatorOffset; euiOffset < C_CAST(uint32_t, (designatorOffset + designatorLength)); ++euiOffset) { - printf("%02" PRIX8 , pageToRead[euiOffset]); + printf("%02" PRIX8, pageToRead[euiOffset]); } printf("\n"); break; @@ -2486,10 +2500,10 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) case 3://Locally Assigned - binary only printf("\t\t\t NAA Type 3 - Locally Assigned\n"); //Locally administered value - printf("\t\t\t Locally Administered Value: %01" PRIX8 , M_Nibble0(pageToRead[designatorOffset]));//print the first nibble, the rest is all individual bytes + printf("\t\t\t Locally Administered Value: %01" PRIX8, M_Nibble0(pageToRead[designatorOffset]));//print the first nibble, the rest is all individual bytes for (uint16_t lavOffset = designatorOffset + 1; lavOffset < (designatorLength + 4); ++lavOffset) { - printf("%02" PRIX8 , pageToRead[lavOffset]); + printf("%02" PRIX8, pageToRead[lavOffset]); } printf("\n"); break; @@ -2521,7 +2535,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) } else { - printf("%02" PRIX8 , pageToRead[unaaOffset]); + printf("%02" PRIX8, pageToRead[unaaOffset]); } } printf("\n"); @@ -2535,13 +2549,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Code set is not set properly! This should be set to 1 for binary!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (association != 1) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Use of this designator with association not set to 1 is reserved!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } { uint16_t relativeTargetPortID = M_BytesTo2ByteValue(pageToRead[designatorOffset + 2], pageToRead[designatorOffset + 3]); @@ -2554,13 +2568,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Code set is not set properly! This should be set to 1 for binary!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (association != 1) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Use of this designator with association not set to 1 is reserved!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } { uint16_t targetPortGroup = M_BytesTo2ByteValue(pageToRead[designatorOffset + 2], pageToRead[designatorOffset + 3]); @@ -2573,13 +2587,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Code set is not set properly! This should be set to 1 for binary!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (association != 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Use of this designator with association not set to 0 is reserved!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } { uint16_t luGroup = M_BytesTo2ByteValue(pageToRead[designatorOffset + 2], pageToRead[designatorOffset + 3]); @@ -2600,23 +2614,23 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Code set is not properly set! This should be set to 3 for UTF8!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } { - char *scsiNameString = NULL; - scsiNameString = C_CAST(char*, calloc(designatorLength + 1, sizeof(char))); + char *scsiNameString = M_NULLPTR; + scsiNameString = C_CAST(char*, safe_calloc(designatorLength + 1, sizeof(char))); if (scsiNameString) { memcpy(scsiNameString, &pageToRead[designatorOffset], designatorLength); //TODO: validate that all characters are UTF8 printf("\t\t\t SCSI Name: %s\n", scsiNameString); - safe_Free(scsiNameString); + safe_free(&scsiNameString); } else { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: failed to allocate memory (%" PRIu16 "B) to read SCSI Name string\n", designatorLength + 1); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } break; @@ -2627,35 +2641,35 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Association is not set to 1! This may cause parsing issues!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } if (!piv) { //This should be an error since we can only parse this if the interface is set. set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Protocol identifier valid bit is not set! Cannot parse this without this bit!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { switch (protocolIdentifier) { case 9://UAS - { - uint8_t deviceAddress = M_GETBITRANGE(pageToRead[designatorOffset], 6, 0); - uint8_t interfaceNumber = pageToRead[designatorOffset + 2]; - printf("\t\t\t UAS Target Port Identifier:\n"); - printf("\t\t\t Device Address: %02" PRIX8 "h\n", deviceAddress); - printf("\t\t\t Interface Number: %02" PRIX8 "h\n", interfaceNumber); - } - break; + { + uint8_t deviceAddress = M_GETBITRANGE(pageToRead[designatorOffset], 6, 0); + uint8_t interfaceNumber = pageToRead[designatorOffset + 2]; + printf("\t\t\t UAS Target Port Identifier:\n"); + printf("\t\t\t Device Address: %02" PRIX8 "h\n", deviceAddress); + printf("\t\t\t Interface Number: %02" PRIX8 "h\n", interfaceNumber); + } + break; case 0xA://SCSI over PCIe - { - uint16_t routingID = M_BytesTo2ByteValue(pageToRead[designatorOffset], pageToRead[designatorOffset + 1]); - printf("\t\t\t PCIe Routing Identifier:\n"); - printf("\t\t\t Routing ID: %04" PRIX16 "h\n", routingID); - } - break; + { + uint16_t routingID = M_BytesTo2ByteValue(pageToRead[designatorOffset], pageToRead[designatorOffset + 1]); + printf("\t\t\t PCIe Routing Identifier:\n"); + printf("\t\t\t Routing ID: %04" PRIX16 "h\n", routingID); + } + break; default://unknown or not defined in SPC5 when this was written printf("\t\t\t Unknown Protocol Specific Port Identifier type!\n"); print_Data_Buffer(&pageToRead[designatorOffset], designatorLength, true); @@ -2678,11 +2692,11 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Designator length should be 18B, but got %" PRIu16 "B\n", designatorLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } for (uint16_t uuidOffset = designatorOffset; uuidOffset < (designatorLength + 4); ++uuidOffset) { - printf("%02" PRIX8 , pageToRead[uuidOffset]); + printf("%02" PRIX8, pageToRead[uuidOffset]); } printf("\n"); break; @@ -2700,12 +2714,12 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) } } //checking if we got an MD5 when we shouldn't have! - if (gotMD5 && (gotEUI64 || gotNAA || gotSCSINameString || gotUUID )) + if (gotMD5 && (gotEUI64 || gotNAA || gotSCSINameString || gotUUID)) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Device reported MD5 designator while also reporting a\n"); printf(" unique identifier as well. This is not allowed per SPC!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (gotMD5 && md5Offset) { @@ -2715,7 +2729,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("\t\t\t MD5 Logical Unit Identifier: "); for (; md5Offset < 16; ++md5Offset) { - printf("%02" PRIX8 , pageToRead[md5Offset]); + printf("%02" PRIX8, pageToRead[md5Offset]); } printf("\n"); } @@ -2736,7 +2750,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: VPD Page length is less than specified in SPC! Expected %" PRIX16 "h, but got %" PRIX16 "h\n", 0x003C, vpdPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2748,7 +2762,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Extended DST time in minutes was reported as zero! This means SCSI DST translation is not available!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2759,13 +2773,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Maximum Sense Length not reported. Will assume %u Bytes\n", SPC3_SENSE_LEN); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (pageToRead[13] > SPC3_SENSE_LEN) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Maximum Sense Length reported as larger than max allowed by SPC! %u Bytes\n", pageToRead[13]); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2794,13 +2808,13 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: VPD Page length is less than specified in SAT! Expected %" PRIX16 "h, but got %" PRIX16 "h\n", 0x0238, vpdPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { - char satVendor[9] = { 0 }; - char satProductID[17] = { 0 }; - char satRevision[5] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, satVendor, 9); + DECLARE_ZERO_INIT_ARRAY(char, satProductID, 17); + DECLARE_ZERO_INIT_ARRAY(char, satRevision, 5); memcpy(satVendor, &pageToRead[8], 8); memcpy(satProductID, &pageToRead[16], 16); memcpy(satRevision, &pageToRead[32], 4); @@ -2808,20 +2822,20 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) scsiDevInfo->vpdData.gotSATVPDPage = true; for (uint8_t iter = 0; iter < 8; ++iter) { - if (!is_ASCII(satVendor[iter]) || !isprint(satVendor[iter])) + if (!safe_isascii(satVendor[iter]) || !safe_isprint(satVendor[iter])) { satVendor[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: SAT Vendor ID contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } memcpy(device->drive_info.bridge_info.t10SATvendorID, satVendor, 8); - if (strlen(satVendor) == 0) + if (safe_strlen(satVendor) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: SAT Vendor ID is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2829,20 +2843,20 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) } for (uint8_t iter = 0; iter < 16; ++iter) { - if (!is_ASCII(satProductID[iter]) || !isprint(satProductID[iter])) + if (!safe_isascii(satProductID[iter]) || !safe_isprint(satProductID[iter])) { satProductID[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: SAT Product ID contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } memcpy(device->drive_info.bridge_info.SATproductID, satProductID, 16); - if (strlen(satProductID) == 0) + if (safe_strlen(satProductID) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: SAT Product ID is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2850,20 +2864,20 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) } for (uint8_t iter = 0; iter < 4; ++iter) { - if (!is_ASCII(satRevision[iter]) || !isprint(satRevision[iter])) + if (!safe_isascii(satRevision[iter]) || !safe_isprint(satRevision[iter])) { satRevision[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: SAT Product Revision contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } memcpy(device->drive_info.bridge_info.SATfwRev, satRevision, 4); - if (strlen(satRevision) == 0) + if (safe_strlen(satRevision) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: SAT Product Revision is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -2936,7 +2950,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: VPD Page length is less than specified in SPC! Expected %" PRIX16 "h, but got %" PRIX16 "h\n", 0x0E, vpdPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -3217,8 +3231,8 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: VPD Page length is less than specified in SBC! Expected %" PRIX16 "h, but got %" PRIX16 "h\n", 0x003C, vpdPageLength); - set_Console_Colors(true, DEFAULT); - } + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + } else { genericVPDPageReadOutput = false; @@ -3230,7 +3244,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("\tOptimal Transfer Length Granularity: "); if (M_BytesTo2ByteValue(pageToRead[6], pageToRead[7]) > 0) { - printf("%" PRIu16 " Logical Blocks\n", M_BytesTo2ByteValue(pageToRead[6], pageToRead[7])); + printf("%" PRIu16 " Logical Blocks\n", M_BytesTo2ByteValue(pageToRead[6], pageToRead[7])); } else { @@ -3366,7 +3380,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: VPD Page length is less than specified in SBC! Expected %" PRIX16 "h, but got %" PRIX16 "h\n", 0x003C, vpdPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -3390,7 +3404,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Reserved value\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } printf("\tProduct Type: "); scsiDevInfo->vpdData.blockCharacteristicsData.productType = pageToRead[6]; @@ -3503,7 +3517,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: VPD Page length is less than specified in SBC! Expected %" PRIX16 "h, but got %" PRIX16 "h\n", 0x0004, vpdPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -3619,7 +3633,7 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { //vendor specific printf("Vendor Specific VPD Page %02" PRIX8 "h\n", supportedPages[vpdIter]); - } + } else { //unknown page @@ -3631,25 +3645,25 @@ static void scsi_VPD_Pages(tDevice *device, ptrScsiDevInformation scsiDevInfo) { print_Data_Buffer(pageToRead, vpdPageLength, true); } - safe_Free_aligned(pageToRead) + safe_Free_aligned(C_CAST(void**, &pageToRead)); } if (pagesread <= dummiedPageCount && dummiedPages)//less than or equal to 1 because it is possible that the only suppored page is the unit serial number! { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NVPD\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.noVPDPages = true; } } -static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) +static eReturnValues scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, HEADING_COLOR); printf("\n====================\n"); printf("Reading Inquiry Data\n"); printf("====================\n"); - set_Console_Colors(true, DEFAULT); - + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + if (SUCCESS == scsi_Inquiry(device, (uint8_t *)&device->drive_info.scsiVpdData.inquiryData, 96, 0, false, false)) { bool continueTesting = false; @@ -3833,10 +3847,10 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf(" This is only expected for OLD SCSI devices. Nothing else should\n"); printf(" report in this format. Raw output is provided which may be usable\n"); printf(" if needed for better legacy device support.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: PRESCSI2\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.preSCSI2InqData = true; print_Data_Buffer(inqPtr, totalInqLength, true); } @@ -3847,20 +3861,20 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) //Check for printable and non-ASCII characters to warn that these are not supposed to be here! for (uint8_t iter = 0; iter < T10_VENDOR_ID_LEN; ++iter) { - if (!is_ASCII(scsiDevInfo->inquiryData.vendorId[iter]) || !isprint(scsiDevInfo->inquiryData.vendorId[iter])) + if (!safe_isascii(scsiDevInfo->inquiryData.vendorId[iter]) || !safe_isprint(scsiDevInfo->inquiryData.vendorId[iter])) { scsiDevInfo->inquiryData.vendorId[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Vendor ID contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } memcpy(device->drive_info.T10_vendor_ident, scsiDevInfo->inquiryData.vendorId, T10_VENDOR_ID_LEN); - if (strlen(scsiDevInfo->inquiryData.vendorId) == 0) + if (safe_strlen(scsiDevInfo->inquiryData.vendorId) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Vendor ID is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -3871,20 +3885,20 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) //Check for printable and non-ASCII characters to warn that these are not supposed to be here! for (uint8_t iter = 0; iter < INQ_DATA_PRODUCT_ID_LEN; ++iter) { - if (!is_ASCII(scsiDevInfo->inquiryData.productId[iter]) || !isprint(scsiDevInfo->inquiryData.productId[iter])) + if (!safe_isascii(scsiDevInfo->inquiryData.productId[iter]) || !safe_isprint(scsiDevInfo->inquiryData.productId[iter])) { scsiDevInfo->inquiryData.productId[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Product ID contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } memcpy(device->drive_info.product_identification, scsiDevInfo->inquiryData.productId, INQ_DATA_PRODUCT_ID_LEN); - if (strlen(scsiDevInfo->inquiryData.productId) == 0) + if (safe_strlen(scsiDevInfo->inquiryData.productId) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Product ID is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -3895,20 +3909,20 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) //Check for printable and non-ASCII characters to warn that these are not supposed to be here! for (uint8_t iter = 0; iter < INQ_DATA_PRODUCT_REV_LEN; ++iter) { - if (!is_ASCII(scsiDevInfo->inquiryData.productRev[iter]) || !isprint(scsiDevInfo->inquiryData.productRev[iter])) + if (!safe_isascii(scsiDevInfo->inquiryData.productRev[iter]) || !safe_isprint(scsiDevInfo->inquiryData.productRev[iter])) { scsiDevInfo->inquiryData.productRev[iter] = ' '; set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Product Revision contains non-ASCII or non-Printable Characters!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } memcpy(device->drive_info.product_revision, scsiDevInfo->inquiryData.productRev, INQ_DATA_PRODUCT_REV_LEN); - if (strlen(scsiDevInfo->inquiryData.productRev) == 0) + if (safe_strlen(scsiDevInfo->inquiryData.productRev) == 0) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Product Revision is empty!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -3933,7 +3947,7 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) scsiDevInfo->inquiryData.versionDescriptors[versionIter] = M_BytesTo2ByteValue(device->drive_info.scsiVpdData.inquiryData[(versionIter * 2) + 58], device->drive_info.scsiVpdData.inquiryData[(versionIter * 2) + 59]); if (scsiDevInfo->inquiryData.versionDescriptors[versionIter] > 0) { - char versionString[20] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, versionString, MAX_VERSION_DESCRIPTOR_STRING_LENGTH); printf("\t%04" PRIX16 " - ", scsiDevInfo->inquiryData.versionDescriptors[versionIter]); decypher_SCSI_Version_Descriptors(scsiDevInfo->inquiryData.versionDescriptors[versionIter], C_CAST(char*, versionString)); printf("%s\n", versionString); @@ -3967,11 +3981,11 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) printf("NOTE: Inquiry data is 36 bytes or less but reports format 2 which should be 96\n"); printf(" bytes. In these bytes version descriptors will be reported and can be used\n"); printf(" to help better understand device capabilities (starting with SPC2)\n\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } - + if (!continueTesting) { return NOT_SUPPORTED; @@ -3981,13 +3995,13 @@ static int scsi_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, ERROR_COLOR); printf("Fatal Error: Unable to get standard inquiry data. Unable to proceed with any more testing!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return FAILURE; } return SUCCESS; } -static int scsi_Capacity_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) +static eReturnValues scsi_Capacity_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) { //Read capacity. Start with 10, then do 16. Emit warnings when 16 doesn't work and the scsi versions is greater than SPC2 //If read capacity 10 comes back saying UINT32_MAX for capacity, warn that this mismatches the SCSI version reported. @@ -3995,9 +4009,9 @@ static int scsi_Capacity_Information(tDevice *device, ptrScsiDevInformation scsi printf("\n========================================\n"); printf("Getting Read Capacity data. 10 & 16 byte\n"); printf("========================================\n"); - set_Console_Colors(true, DEFAULT); - uint8_t readCapacityData[32] = { 0 }; - int readCap10Result = SUCCESS, readCap16Result = SUCCESS; + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + DECLARE_ZERO_INIT_ARRAY(uint8_t, readCapacityData, 32); + eReturnValues readCap10Result = SUCCESS, readCap16Result = SUCCESS; if (SUCCESS == (readCap10Result = scsi_Read_Capacity_10(device, readCapacityData, 8))) { scsiDevInfo->readCapData.rc10MaxLBA = M_BytesTo4ByteValue(readCapacityData[0], readCapacityData[1], readCapacityData[2], readCapacityData[3]); @@ -4014,7 +4028,7 @@ static int scsi_Capacity_Information(tDevice *device, ptrScsiDevInformation scsi printf("WARNING: Failed read capacity 10. While this command is superceeded by read capacity 16,\n"); printf(" supporting it helps legacy system support and software. If not supported, it should\n"); printf(" at least fail gracefully and report \"Invalid Operation Code\"\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } memset(readCapacityData, 0, 32); if (SUCCESS == (readCap16Result = scsi_Read_Capacity_16(device, readCapacityData, 32))) @@ -4038,7 +4052,7 @@ static int scsi_Capacity_Information(tDevice *device, ptrScsiDevInformation scsi printf(" to physical block relationships so that read/write can be properly aligned for the device.\n"); printf(" this command also reports if logical block provisioning management is enabled and whether\n"); printf(" or not zeros are reported when reading an unmapped LBA.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } if (readCap16Result == SUCCESS && readCap10Result == SUCCESS) @@ -4047,27 +4061,27 @@ static int scsi_Capacity_Information(tDevice *device, ptrScsiDevInformation scsi { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Block length does not match between read capacity commands!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } if (scsiDevInfo->readCapData.rc10MaxLBA != UINT32_MAX && scsiDevInfo->readCapData.rc10MaxLBA != scsiDevInfo->readCapData.rc16MaxLBA) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Max LBA does not match between read capacity commands!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } return SUCCESS; } -static int use_Mode_Sense_6(tDevice * device, uint8_t pageCode, bool *use6Byte) +static eReturnValues use_Mode_Sense_6(tDevice * device, uint8_t pageCode, bool *use6Byte) { - int ret = SUCCESS; + eReturnValues ret = SUCCESS; if (!use6Byte) { return BAD_PARAMETER; } //TODO: This code currently always sets DBD, which is fine for SCSI2+, but not ok for earlier devices as that bit wasn't even a thought. - if (SUCCESS != scsi_Mode_Sense_10(device, pageCode, 0, 0, false, false, MPC_CURRENT_VALUES, NULL)) + if (SUCCESS != scsi_Mode_Sense_10(device, pageCode, 0, 0, false, false, MPC_CURRENT_VALUES, M_NULLPTR)) { //if invalid operation code, try again with 6 byte command. bool tryAnotherPage = false; @@ -4077,7 +4091,7 @@ static int use_Mode_Sense_6(tDevice * device, uint8_t pageCode, bool *use6Byte) if (senseFields.scsiStatusCodes.senseKey == SENSE_KEY_ILLEGAL_REQUEST && senseFields.scsiStatusCodes.asc == 0x20 && senseFields.scsiStatusCodes.ascq == 0x00) { //didn't like the operation code, so retrying with mode sense 6 - if (SUCCESS == scsi_Mode_Sense_6(device, pageCode, 0, 0, false, MPC_CURRENT_VALUES, NULL)) + if (SUCCESS == scsi_Mode_Sense_6(device, pageCode, 0, 0, false, MPC_CURRENT_VALUES, M_NULLPTR)) { *use6Byte = true; } @@ -4085,10 +4099,10 @@ static int use_Mode_Sense_6(tDevice * device, uint8_t pageCode, bool *use6Byte) { get_Sense_Data_Fields(device->drive_info.lastCommandSenseData, SPC3_SENSE_LEN, &senseFields); if (senseFields.scsiStatusCodes.senseKey == SENSE_KEY_ILLEGAL_REQUEST && senseFields.scsiStatusCodes.asc == 0x20 && senseFields.scsiStatusCodes.ascq == 0x00) - { + { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: This device does not appear to support either mode sense 10 or mode sense 6!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return FAILURE; } else @@ -4118,9 +4132,9 @@ static int use_Mode_Sense_6(tDevice * device, uint8_t pageCode, bool *use6Byte) return ret; } -static int get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t subPageCode, bool sixByte, uint8_t **dataBuffer /*to allow for reallocation/resize if necessary to get the full page*/, uint32_t *dataBufferLength) +static eReturnValues get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t subPageCode, bool sixByte, uint8_t **dataBuffer /*to allow for reallocation/resize if necessary to get the full page*/, uint32_t *dataBufferLength) { - int ret = SUCCESS; + eReturnValues ret = SUCCESS; memset(*dataBuffer, 0, *dataBufferLength); if (sixByte) { @@ -4145,14 +4159,14 @@ static int get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t s { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Incorrect page returned from mode sense 6. Expected %02" PRIX8 "h, but got %02" PRIX8 "h\n", pageCode, readpageCode); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); ret = FAILURE; } else if (subpageFormat && subPageCode != readsubpage) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Incorrect subpage returned from mode sense 6. Expected %02" PRIX8 "h, but got %02" PRIX8 "h\n", subPageCode, readsubpage); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); ret = FAILURE; } else if (subPageCode != 0 && !subpageFormat) @@ -4160,12 +4174,12 @@ static int get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t s set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NMSP\n");//mode page subpages are not supported by this device and it does not properly validate all fields of the CDB device->drive_info.passThroughHacks.scsiHacks.noModeSubPages = true; - set_Console_Colors(true, DEFAULT); - } + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + } else { //Everything looks ok, so double check the datalength - pageLengthValidation += pageLength + MODE_PARAMETER_HEADER_6_LEN + blockDescriptorLength; + pageLengthValidation += C_CAST(uint8_t, pageLength + MODE_PARAMETER_HEADER_6_LEN + blockDescriptorLength); if (*dataBufferLength < pageLengthValidation) { //reallocate enough data and reread the page. @@ -4207,14 +4221,14 @@ static int get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t s { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Incorrect page returned from mode sense 6. Expected %02" PRIX8 "h, but got %02" PRIX8 "h\n", pageCode, readpageCode); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); ret = FAILURE; } else if (subpageFormat && subPageCode != readsubpage) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Incorrect subpage returned from mode sense 6. Expected %02" PRIX8 "h, but got %02" PRIX8 "h\n", subPageCode, readsubpage); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); ret = FAILURE; } else if (subPageCode != 0 && !subpageFormat) @@ -4222,12 +4236,12 @@ static int get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t s set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NMSP\n");//mode page subpages are not supported by this device and it does not properly validate all fields of the CDB device->drive_info.passThroughHacks.scsiHacks.noModeSubPages = true; - set_Console_Colors(true, DEFAULT); - } + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + } else { //Everything looks ok, so double check the datalength - pageLengthValidation += pageLength + MODE_PARAMETER_HEADER_10_LEN + blockDescriptorLength; + pageLengthValidation += C_CAST(uint8_t, pageLength + MODE_PARAMETER_HEADER_10_LEN + blockDescriptorLength); if (*dataBufferLength < pageLengthValidation) { //reallocate enough data and reread the page. @@ -4250,7 +4264,7 @@ static int get_SCSI_Mode_Page_Data(tDevice * device, uint8_t pageCode, uint8_t s } //TODO: Validate or check for default, changable, and saved values? Only checking current right now - TJE -static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) +static eReturnValues scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) { bool successfullyReadAtLeastOnePage = false; bool use6Byte = false; @@ -4258,9 +4272,9 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI printf("\n==========================\n"); printf("Checking Mode Page Support\n"); printf("==========================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //Attempting mode sense 10 since nearly EVERYTHING should support it. The only exception is REALLY old SCSI drives. - int sixTest = use_Mode_Sense_6(device, MP_CONTROL, &use6Byte); + eReturnValues sixTest = use_Mode_Sense_6(device, MP_CONTROL, &use6Byte); if (SUCCESS != sixTest) { if (use6Byte) @@ -4268,7 +4282,7 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: MP6\n"); device->drive_info.passThroughHacks.scsiHacks.mode6bytes = true; - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //TODO: add this to the passthrough hacks structure. } if (sixTest == NOT_SUPPORTED) @@ -4276,7 +4290,7 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI set_Console_Colors(true, WARNING_COLOR); printf("WARNING: This device does not seem to support any standard mode pages. Skipping all mode page checks\n"); printf(" This should only happen on SCSI (1) and earlier (SASI) devices!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return NOT_SUPPORTED; } else @@ -4284,11 +4298,11 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NMP\n"); device->drive_info.passThroughHacks.scsiHacks.noModePages = true; - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); set_Console_Colors(true, ERROR_COLOR); printf("ERROR: This device doesn't support ANY mode sense commands. Mode sense commands can convey device support and change\n"); printf(" device settings/capabilties. This can be especially important for disabling write caching for backups.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } return sixTest; } @@ -4298,16 +4312,16 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI modeHeaderLength = MODE_PARAMETER_HEADER_6_LEN; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: MP6\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.mode6bytes = true; } uint32_t commonModeDataLength = modeHeaderLength + 4 + 8;//Header length + 4 bytes to check initial size of a mode page + 8 bytes for typical short block descriptor. uint32_t modeDataLength = 0; - uint8_t *modeData = NULL; + uint8_t *modeData = M_NULLPTR; //control mode page modeDataLength = MP_CONTROL_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4344,11 +4358,11 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI } scsiDevInfo->modeData.controlData.extDSTCompletionTimeSeconds = M_BytesTo2ByteValue(modeData[offset + 10], modeData[offset + 11]); printf("\tExt DST Completion Time (Seconds): %" PRIu16 "\n", scsiDevInfo->modeData.controlData.extDSTCompletionTimeSeconds); - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); //control extension mode page (not 6 byte, and check if it reports correctly) modeDataLength = MP_CONTROL_EXTENSION_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4376,13 +4390,13 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI scsiDevInfo->modeData.controlExtData.maxSenseDataLength = modeData[offset + 6]; printf("\tMaximum Sense Data Length: %" PRIu8 "\n", scsiDevInfo->modeData.controlExtData.maxSenseDataLength); } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); } - safe_Free_aligned(modeData) - + safe_Free_aligned(C_CAST(void**, &modeData)); + //read write error recovery mode page modeDataLength = MP_READ_WRITE_ERROR_RECOVERY_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4413,7 +4427,7 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI { printf("Enabled\n"); } - else + else { printf("Disabled\n"); } @@ -4423,17 +4437,17 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI { printf("Enabled\n"); } - else + else { printf("Disabled\n"); } scsiDevInfo->modeData.rwErrRecData.recoveryTimeLimit = M_BytesTo2ByteValue(modeData[offset + 10], modeData[offset + 11]); printf("\tRecovery Time Limit: %" PRIu16 "\n", scsiDevInfo->modeData.rwErrRecData.recoveryTimeLimit); } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); //caching mode page modeDataLength = MP_CACHING_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4482,11 +4496,11 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI } } } - safe_Free_aligned(modeData) - + safe_Free_aligned(C_CAST(void**, &modeData)); + //rigid disk geometry page modeDataLength = MP_RIGID_DISK_GEOMETRY_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4560,11 +4574,11 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI break; } } - safe_Free_aligned(modeData) - + safe_Free_aligned(C_CAST(void**, &modeData)); + //informational exceptions mode page modeDataLength = MP_INFORMATION_EXCEPTIONS_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4622,10 +4636,10 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI scsiDevInfo->modeData.infoExcepData.mrie = M_Nibble0(modeData[offset + 3]); printf("\tMethod Of Reporting Informational Exceptions (MRIE): %" PRIX8 "h\n", scsiDevInfo->modeData.infoExcepData.mrie); } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); //power condition control mode page modeDataLength = MP_POWER_CONDITION_LEN + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4684,7 +4698,7 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI } } } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); //TODO: The next 2 are ATA specific. Attempt to only read them when we suspect an ATA drive. //if () //ATA AND the passthrough hack for not supporting subpages is NOT set { @@ -4692,7 +4706,7 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI { //pata control mode page - only read if the device could be a PATA drive. modeDataLength = 8 + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4730,11 +4744,11 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI scsiDevInfo->modeData.pataCtrlData.udma5 = M_ToBool(modeData[offset + 5] & BIT5); scsiDevInfo->modeData.pataCtrlData.udma6 = M_ToBool(modeData[offset + 5] & BIT6); } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); } //ata power condition mode page modeDataLength = 16 + commonModeDataLength; - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4772,11 +4786,11 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI scsiDevInfo->modeData.ataPwrConditionData.apmValue = modeData[offset + 6]; printf("\tAPM Value: %" PRIX8 "h\n", scsiDevInfo->modeData.ataPwrConditionData.apmValue); } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); } //Check for vendor specific page 0? May help detect true SCSI devices, but nothing says a translator cannot implement it. modeDataLength = UINT8_MAX;//try this size since it's unlikely this page will be this size, but it should be more than enough memory. - modeData = C_CAST(uint8_t *, calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + modeData = C_CAST(uint8_t *, safe_calloc_aligned(modeDataLength, sizeof(uint8_t), device->os_info.minimumAlignment)); if (!modeData) { return MEMORY_FAILURE; @@ -4807,33 +4821,33 @@ static int scsi_Mode_Information(tDevice *device, ptrScsiDevInformation scsiDevI set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NMP\n"); device->drive_info.passThroughHacks.scsiHacks.noModePages = true; - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); set_Console_Colors(true, WARNING_COLOR); printf("WARNING: This device does not seem to support any standard mode pages. Multiple pages were attempted, but none were read successfully.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return NOT_SUPPORTED; } - safe_Free_aligned(modeData) + safe_Free_aligned(C_CAST(void**, &modeData)); return SUCCESS; } //TODO: we can clean up the loops in each case to most likely a single loop somewhere, but will need to figure out a method to save the data fields we care about...-TJE -static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) +static eReturnValues scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevInfo) { set_Console_Colors(true, HEADING_COLOR); printf("\n==========================\n"); printf("Testing for SCSI Log Pages\n"); printf("==========================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //Make sure on the first log sense, if it fails, we check for invalid operation code. If invalid code, test is over since the command isn't supported. //Let the user know about this though! - uint8_t supportPages[255] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, supportPages, 255); if (SUCCESS == scsi_Log_Sense_Cmd(device, false, LPC_CUMULATIVE_VALUES, LP_SUPPORTED_LOG_PAGES, 0, 0, supportPages, 255)) { bool hasSubpages = false; //we should have the supported logs at this point. //Now we need to attempt to read the list of supported subpages as well. WARNING: some device may respond because they don't properly validate reserved fields. Need to catch this!!! - uint8_t supportedPagesAndSubpages[255] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, supportedPagesAndSubpages, 255); if (SUCCESS == scsi_Log_Sense_Cmd(device, false, LPC_CUMULATIVE_VALUES, LP_SUPPORTED_LOG_PAGES_AND_SUBPAGES, 0xFF, 0, supportedPagesAndSubpages, 255)) { //While we got successful status for subpages, we need to validate the data!!! @@ -4841,7 +4855,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NLPS\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.noLogSubPages = true; printf("This device does NOT report log page subpages properly! Do not attempt to read ANY subpages as it only checks the page code!\n"); } @@ -4868,7 +4882,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Length of subpages does not appear to make sense. It should be AT LEAST twice as long as without reporting subpages.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //printf(" One more level analysis is allowed before this is considered a buggy device that reports incorrectly when asking for subpages.\n"); //TODO: final level of analysis...looping and checking to see if a single page is missing or not. // when completed, uncomment the above printf....if this case actually happens, will need another hack for this device since it reports correctly formatted data, but misses reporting some pages. @@ -4880,7 +4894,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NLPS\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); printf("This device reports success from asking for subpage list, BUT doesn't report properly\n"); hasSubpages = false; device->drive_info.passThroughHacks.scsiHacks.noLogSubPages = true; @@ -4894,7 +4908,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Data looks completely invalid! Cancelling SCSI log page test!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return FAILURE; } } @@ -4926,9 +4940,9 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn printf("\tFound page %02" PRIX8 "h\n", pageCode); } //TODO: Read the length of the current page/subpage, then read the whole thing. Keep this pointer for the rest of the loop below. - uint8_t *pageToRead = C_CAST(uint8_t*, calloc_aligned(logPageLength, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *pageToRead = C_CAST(uint8_t*, safe_calloc_aligned(logPageLength, sizeof(uint8_t), device->os_info.minimumAlignment)); - if (SUCCESS == scsi_Log_Sense_Cmd(device, false, LPC_CUMULATIVE_VALUES,pageCode,subPageCode, 0, pageToRead, logPageLength)) + if (SUCCESS == scsi_Log_Sense_Cmd(device, false, LPC_CUMULATIVE_VALUES, pageCode, subPageCode, 0, pageToRead, logPageLength)) { logPageLength = M_BytesTo2ByteValue(pageToRead[2], pageToRead[3]); uint8_t* temp = realloc_aligned(pageToRead, logPageLength, logPageLength + 4, device->os_info.minimumAlignment); @@ -4947,14 +4961,14 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Expected page %" PRIX8 "h, but got %" PRIX8 "h\n", pageCode, C_CAST(uint8_t, M_GETBITRANGE(pageToRead[0], 5, 0))); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (pageToRead[1] != subPageCode) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Expected subpage %" PRIX8 "h, but got %" PRIX8 "h\n", subPageCode, pageToRead[1]); - set_Console_Colors(true, DEFAULT); - } + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + } else { readLogPage = true; @@ -4966,7 +4980,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Expected page %" PRIX8 "h, but got %" PRIX8 "h\n", pageCode, C_CAST(uint8_t, M_GETBITRANGE(pageToRead[0], 5, 0))); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -4979,14 +4993,14 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Failed to read page %02" PRIX8 "h-%02" PRIX8 "h. Was reported as supported, but cannot be read.\n", pageCode, subPageCode); printf(" Attempted to read %02" PRIu16 " bytes as reported by device.\n", logPageLength); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } else { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Unable to allocate memory to read %" PRIu16 "B of page %02" PRIX8 "h-%02" PRIX8 "h\n", logPageLength, pageCode, subPageCode); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } @@ -5723,7 +5737,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn printf("\tPending Defect Count: %" PRIu32 "\n", scsiDevInfo->logData.pendingDefectsData.pendingDefectsCount); break; default: - if (parameterCode >0 && parameterCode <= 0xF000) + if (parameterCode > 0 && parameterCode <= 0xF000) { printf("\tPending Defect %" PRIu16 "\n", parameterCode); uint32_t poh = M_BytesTo4ByteValue(pageToRead[offset + 4], pageToRead[offset + 5], pageToRead[offset + 6], pageToRead[offset + 7]); @@ -6012,7 +6026,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn { print_Data_Buffer(pageToRead, logPageLength, true); } - safe_Free_aligned(pageToRead) + safe_Free_aligned(C_CAST(void**, &pageToRead)); } } else @@ -6025,7 +6039,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn //Invalid operation code, so this device does not support log sense commands. set_Console_Colors(true, NOTE_COLOR); printf("NOTE: Skipping SCSI Log test since device reported invalid operation code.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -6037,7 +6051,7 @@ static int scsi_Log_Information(tDevice *device, ptrScsiDevInformation scsiDevIn device->drive_info.passThroughHacks.scsiHacks.noLogPages = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NLP\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } return SUCCESS; } @@ -6051,9 +6065,9 @@ typedef struct _scsiRWSupport bool nonZeroSectorCountRequired; }scsiRWSupport, *ptrScsiRWSupport; -static int scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWSupport rwSupport, bool testZeroLengthTransfersToo) +static eReturnValues scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWSupport rwSupport, bool testZeroLengthTransfersToo) { - if (!device || ! rwSupport) + if (!device || !rwSupport) { return BAD_PARAMETER; } @@ -6071,15 +6085,15 @@ static int scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWS printf("Checking SCSI Read/Write Command Support\n"); printf("========================================\n"); } - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); - uint8_t *ptrData = NULL; + uint8_t *ptrData = M_NULLPTR; uint32_t transferLength = 0; uint32_t transferLengthBytes = 0; if (!zeroLengthTransfers) { transferLength = 1; - ptrData = C_CAST(uint8_t *, calloc_aligned(device->drive_info.deviceBlockSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + ptrData = C_CAST(uint8_t *, safe_calloc_aligned(device->drive_info.deviceBlockSize, sizeof(uint8_t), device->os_info.minimumAlignment)); transferLengthBytes = device->drive_info.deviceBlockSize; if (!ptrData) { @@ -6091,7 +6105,7 @@ static int scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWS rwSupport->sixBytes = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RW6\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.readWrite.available = true; device->drive_info.passThroughHacks.scsiHacks.readWrite.rw6 = true; } @@ -6100,44 +6114,44 @@ static int scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWS { set_Console_Colors(true, NOTE_COLOR); printf("NOTE: Skipping R6 since zero length has a different meaning than other commands\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } //read 10 - if (SUCCESS == scsi_Read_10(device, 0, false, false, false, 0, 0, C_CAST(uint16_t, transferLength), ptrData,transferLengthBytes)) + if (SUCCESS == scsi_Read_10(device, 0, false, false, false, 0, 0, C_CAST(uint16_t, transferLength), ptrData, transferLengthBytes)) { rwSupport->tenBytes = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RW10\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.readWrite.available = true; device->drive_info.passThroughHacks.scsiHacks.readWrite.rw10 = true; } //read 12 - if (SUCCESS == scsi_Read_12(device, 0, false, false, false, 0, 0, transferLength,ptrData,transferLengthBytes)) + if (SUCCESS == scsi_Read_12(device, 0, false, false, false, 0, 0, transferLength, ptrData, transferLengthBytes)) { rwSupport->twelveBytes = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RW12\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.readWrite.available = true; device->drive_info.passThroughHacks.scsiHacks.readWrite.rw12 = true; } //read 16 - if (SUCCESS == scsi_Read_16(device, 0, false, false, false, 0, 0, transferLength,ptrData,transferLengthBytes)) + if (SUCCESS == scsi_Read_16(device, 0, false, false, false, 0, 0, transferLength, ptrData, transferLengthBytes)) { rwSupport->sixteenBytes = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: RW16\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.readWrite.available = true; device->drive_info.passThroughHacks.scsiHacks.readWrite.rw16 = true; } - safe_Free_aligned(ptrData) + safe_Free_aligned(C_CAST(void**, &ptrData)); if (testZeroLengthTransfersToo) { @@ -6147,7 +6161,7 @@ static int scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWS { set_Console_Colors(true, NOTE_COLOR); printf("NOTE: Skipping testing for zero length transfers. This test should be done for highest compatibilty testing!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } @@ -6155,12 +6169,12 @@ static int scsi_Read_Check(tDevice *device, bool zeroLengthTransfers, ptrScsiRWS { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Failed to find any support read commands by the device!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); rwSupport->nonZeroSectorCountRequired = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NZTL\n");//non-zero transfer length - set_Console_Colors(true, DEFAULT); - scsi_Test_Unit_Ready(device, NULL);//try to clear errors before leaving this test + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); + scsi_Test_Unit_Ready(device, M_NULLPTR);//try to clear errors before leaving this test return FAILURE; } return SUCCESS; @@ -6216,7 +6230,7 @@ static bool does_Sense_Data_Show_Invalid_Field_In_CDB(tDevice *device) // return invalidField; // } -static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCmds) +static eReturnValues other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCmds) { if (!device || !scsiCmds) { @@ -6227,9 +6241,9 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm printf("\n===========================\n"); printf("Testing Other SCSI Commands\n"); printf("===========================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); - uint8_t scsiDataBytes[512] = { 0 };//used by each command + DECLARE_ZERO_INIT_ARRAY(uint8_t, scsiDataBytes, 512);//used by each command scsiStatus blah; memset(&blah, 0, sizeof(scsiStatus)); @@ -6241,7 +6255,7 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Test unit ready command total failure. This is a critical command!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } if (SUCCESS == scsi_Report_Luns(device, 0, 256, scsiDataBytes)) @@ -6252,16 +6266,16 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Report LUNS failed. This is a critical command!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } - + if (SUCCESS == scsi_SecurityProtocol_In(device, 0, 0, false, 512, scsiDataBytes)) { scsiCmds->securityProtocol = true; device->drive_info.passThroughHacks.scsiHacks.securityProtocolSupported = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SECPROT\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { @@ -6277,16 +6291,16 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm device->drive_info.passThroughHacks.scsiHacks.securityProtocolSupported = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SECPROTI512\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Device reported in a way that suggests that security protocol commands work, but no security protocol commands were successful\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); set_Console_Colors(true, LIKELY_HACK_COLOR); printf("Likely HACK FOUND: SECPROTI512\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.securityProtocolWithInc512 = true; device->drive_info.passThroughHacks.scsiHacks.securityProtocolSupported = true; } @@ -6295,7 +6309,7 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Security protocol in failed. Access to device security subsystems may be inaccessible or limited!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } @@ -6304,7 +6318,7 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm scsiCmds->reportAllSupportedOperationCodes = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: REPALLOP\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.reportAllOpCodes = true; } else @@ -6313,13 +6327,13 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Reporting supported operation codes failed! This command does not appear to be known by the device.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (does_Sense_Data_Show_Invalid_Field_In_CDB(device)) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Reporting all supported operation codes is not supported! Will attempt requesting a single operation code.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } if (!does_Sense_Data_Show_Invalid_OP(device)) @@ -6330,14 +6344,14 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm scsiCmds->reportSingleSupportedOperationCode = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SUPSOP\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.reportSingleOpCodes = true; } else { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Reporting support for single requested operation codes failed! Unable to request command support from the device!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } @@ -6345,14 +6359,14 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NRSUPOP\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.scsiHacks.noReportSupportedOperations = true; } printf("Testing SCSI default self-test.\n"); //send diagnostic for default device self test. Wait up to 5 minutes for this command since some devices could take longer to process this //TODO: it is possible for self-test to fail, which we should catch since it performed the test and didn't return invalid operation code or invalid field in CDB - /*int selfTestResult =*/ scsi_Send_Diagnostic(device, 0, 0, 1, 0, 0, 0, NULL, 0, 5 * 60); + /*eReturnValues selfTestResult =*/ scsi_Send_Diagnostic(device, 0, 0, 1, 0, 0, 0, M_NULLPTR, 0, 5 * 60); if (!does_Sense_Data_Show_Invalid_OP(device)) { scsiCmds->sendDiagnostic = true; @@ -6362,7 +6376,7 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Default self-test is not available.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } //TODO: add testing for diagnostic pages (try to get a list of pages) @@ -6371,33 +6385,33 @@ static int other_SCSI_Cmd_Support(tDevice *device, ptrOtherSCSICmdSupport scsiCm } #include <math.h> -static int scsi_Error_Handling_Test(tDevice *device, double *badCommandRelativeTimeToGood) +static eReturnValues scsi_Error_Handling_Test(tDevice *device, double *badCommandRelativeTimeToGood) { if (!device) { return BAD_PARAMETER; } - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); set_Console_Colors(true, HEADING_COLOR); printf("\n==============================================\n"); printf("Testing Error Handling Of Unsupported Commands\n"); printf("==============================================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //need to figure out commands to try, and time each and everyone. //Start with determining a baseline from a 3-4 commands (TUR after each) //Now that a base is established, start sending 10 or more unsupported commands and check how long the last one took. If it's near the baseline, it's fine //If not, and the time is significantly longer, then we know that sending test unit ready commands after each failed command is necessary for it to perform well. #define MAX_COMMANDS_TO_TRY 16 - uint64_t commandTimes[MAX_COMMANDS_TO_TRY + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint64_t, commandTimes, MAX_COMMANDS_TO_TRY + 1); uint8_t commandIter = 0; - uint8_t dataBuffer[255] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, dataBuffer, 255); scsi_Inquiry(device, dataBuffer, 96, 0, false, false);//starting with a good command. commandTimes[commandIter] = device->drive_info.lastCommandTimeNanoSeconds; ++commandIter; //Now try one that is likely to not be supported and return invalid field in CDB (vendor specific page of some kind or another...try something in middle of range to hopefully avoid something that may actually be implented.) - int ret = SUCCESS; + eReturnValues ret = SUCCESS; uint8_t pageCode = 0x2B; uint8_t subpage = 0x01; //page 2B, 01 should be an invalid page-subpage combination which should generate invalid field in CDB... @@ -6411,11 +6425,11 @@ static int scsi_Error_Handling_Test(tDevice *device, double *badCommandRelativeT } commandTimes[commandIter] = device->drive_info.lastCommandTimeNanoSeconds; ++commandIter; - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); ret = scsi_Mode_Sense_10(device, pageCode, 255, subpage, true, false, MPC_CURRENT_VALUES, dataBuffer); commandTimes[commandIter] = device->drive_info.lastCommandTimeNanoSeconds; ++commandIter; - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); //now average the 3 times we got. uint64_t averageCommandTimeNS = (commandTimes[1] + commandTimes[2] + commandTimes[0]) / 3; @@ -6463,33 +6477,33 @@ static int scsi_Error_Handling_Test(tDevice *device, double *badCommandRelativeT device->drive_info.passThroughHacks.turfValue = C_CAST(uint8_t, round(xTimesHigher)); set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: TURF%" PRIu8 "\n", device->drive_info.passThroughHacks.turfValue); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.testUnitReadyAfterAnyCommandFailure = true; - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); } else if (ret == OS_PASSTHROUGH_FAILURE) { set_Console_Colors(true, LIKELY_HACK_COLOR); printf("Likely HACK FOUND: TURF%" PRIu8 "\n", 33);//setting 33...this should be sooo much higher and worse that this should remain true for a long long time. - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.testUnitReadyAfterAnyCommandFailure = true; device->drive_info.passThroughHacks.turfValue = 33; - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); } else if (averageFromBadCommands == 0) { set_Console_Colors(true, LIKELY_HACK_COLOR); printf("Likely HACK FOUND: TURF%" PRIu8 "\n", 34);//setting 34...this helps differentiate from the issue above - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); device->drive_info.passThroughHacks.testUnitReadyAfterAnyCommandFailure = true; device->drive_info.passThroughHacks.turfValue = 34; - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); } return SUCCESS; } -static int sct_GPL_Test(tDevice *device, bool smartSupported, bool gplSupported, bool sctSupported) +static eReturnValues sct_GPL_Test(tDevice *device, bool smartSupported, bool gplSupported, bool sctSupported) { if (!device) { @@ -6499,11 +6513,11 @@ static int sct_GPL_Test(tDevice *device, bool smartSupported, bool gplSupported, printf("\n============\n"); printf("SCT-GPL Test\n"); printf("============\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); if (sctSupported && smartSupported && gplSupported) { bool smartWorked = false; - uint8_t sctStatus[512] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, sctStatus, 512); printf("This test tries reading the SCT status log with SMART and GPL commands.\n"); printf("This is done to test if one of these causes a SATL to hang as has been seen in the past.\n"); printf("If this test hangs the device, it will need to be unplugged and the tool rerun without the sctgpl test.\n"); @@ -6520,7 +6534,7 @@ static int sct_GPL_Test(tDevice *device, bool smartSupported, bool gplSupported, { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Something went wrong trying to read the SCT status log!!!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } //now GPL printf("\tTesting with read log ext\n"); @@ -6534,7 +6548,7 @@ static int sct_GPL_Test(tDevice *device, bool smartSupported, bool gplSupported, { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SCTSM\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); printf("\t\tA retest is recommended with this test turned off. Devices with this hack\n"); printf("\t\toften do not recover properly and need a full power cycle once this issue is\n"); printf("\t\ttested and identified.\n"); @@ -6542,7 +6556,7 @@ static int sct_GPL_Test(tDevice *device, bool smartSupported, bool gplSupported, } set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Something went wrong trying to read the SCT status log!!!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } return SUCCESS; } @@ -6585,7 +6599,7 @@ static void setup_ATA_ID_Info(ptrPassthroughTestParams inputs, bool *smartSuppor //word 117 is only valid when word 106 bit 12 is set if ((ident_word[106] & BIT12) == BIT12) { - inputs->device->drive_info.bridge_info.childDeviceBlockSize = M_BytesTo2ByteValue(ident_word[118], ident_word[117]); + inputs->device->drive_info.bridge_info.childDeviceBlockSize = M_WordsTo4ByteValue(ident_word[118], ident_word[117]); inputs->device->drive_info.bridge_info.childDeviceBlockSize *= 2; //convert to words to bytes } else //means that logical sector size is 512bytes @@ -6651,14 +6665,14 @@ static void setup_ATA_ID_Info(ptrPassthroughTestParams inputs, bool *smartSuppor // head = identifyData[6];//Word3 // sector = identifyData[12];//Word6 //} - uint32_t lba = cylinder * head * sector; + uint32_t lba = C_CAST(uint32_t, cylinder) * C_CAST(uint32_t, head) * C_CAST(uint32_t, sector); if (lba == 0) { //Cannot use "current" settings on this drive...use default (really old drive) cylinder = M_BytesTo2ByteValue(identifyData[3], identifyData[2]);//word 1 head = identifyData[6];//Word3 sector = identifyData[12];//Word6 - lba = cylinder * head * sector; + lba = C_CAST(uint32_t, cylinder) * C_CAST(uint32_t, head) * C_CAST(uint32_t, sector); } inputs->device->drive_info.bridge_info.childDeviceMaxLba = lba; } @@ -6723,7 +6737,7 @@ static void setup_ATA_ID_Info(ptrPassthroughTestParams inputs, bool *smartSuppor inputs->device->drive_info.ata_Options.nativeCommandQueuingSupported = true; } //check if the device is parallel or serial - uint8_t transportType = (ident_word[222] & (BIT15 | BIT14 | BIT13 | BIT12)) >> 12; + uint8_t transportType = C_CAST(uint8_t, (ident_word[222] & (BIT15 | BIT14 | BIT13 | BIT12)) >> 12); switch (transportType) { case 0x00://parallel @@ -6815,9 +6829,9 @@ static void setup_ATA_ID_Info(ptrPassthroughTestParams inputs, bool *smartSuppor return; } -static int sat_Test_Identify(tDevice *device, uint8_t *ptrData, uint32_t dataSize, uint8_t cdbSize) +static eReturnValues sat_Test_Identify(tDevice *device, uint8_t *ptrData, uint32_t dataSize, uint8_t cdbSize) { - int ret = UNKNOWN; + eReturnValues ret = UNKNOWN; ataPassthroughCommand identify; memset(&identify, 0, sizeof(ataPassthroughCommand)); identify.commandType = ATA_CMD_TYPE_TASKFILE; @@ -6887,12 +6901,12 @@ static int sat_Test_Identify(tDevice *device, uint8_t *ptrData, uint32_t dataSiz return ret; } -static int sat_Ext_Cmd_With_A1_When_Possible_Test(tDevice *device) +static eReturnValues sat_Ext_Cmd_With_A1_When_Possible_Test(tDevice *device) { - int ret = NOT_SUPPORTED; + eReturnValues ret = NOT_SUPPORTED; if (device->drive_info.ata_Options.generalPurposeLoggingSupported) { - uint8_t log[512] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, log, 512); printf("Testing if it is possible to issue limited Ext (48bit) commands with A1 CDB\n"); device->drive_info.passThroughHacks.ataPTHacks.a1ExtCommandWhenPossible = true; if (SUCCESS == ata_Read_Log_Ext(device, ATA_LOG_DIRECTORY, 0, log, 512, false, 0)) @@ -6900,7 +6914,7 @@ static int sat_Ext_Cmd_With_A1_When_Possible_Test(tDevice *device) //TODO: Validate the return data??? set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: A1EXT\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); ret = SUCCESS; } else @@ -6918,7 +6932,7 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf printf("\n=====================================\n"); printf("Checking SAT ATA-passthrough commands\n"); printf("=====================================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); bool satSupported = false; bool twelveByteSupported = false; bool sixteenByteSupported = false; @@ -6927,7 +6941,7 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf inputs->device->drive_info.passThroughHacks.passthroughType = ATA_PASSTHROUGH_SAT; //inputs->device->drive_info.passThroughHacks.ataPTHacks.useA1SATPassthroughWheneverPossible = true; //forcing A1 first. uint8_t *identifyData = (uint8_t*)&inputs->device->drive_info.IdentifyData.ata.Word000; - int satRet = sat_Test_Identify(inputs->device, identifyData, 512, 12); + eReturnValues satRet = sat_Test_Identify(inputs->device, identifyData, 512, 12); if (SUCCESS == satRet || WARN_INVALID_CHECKSUM == satRet) { //TODO: Validate Identify data! @@ -6959,14 +6973,14 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: A1\n");//useA1SATPassthroughWheneverPossible - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //inputs->device->drive_info.passThroughHacks.ataPTHacks.useA1SATPassthroughWheneverPossible = true; } else if (!twelveByteSupported && sixteenByteSupported) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NA1\n");//a1NeverSupported - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.ataPTHacks.a1NeverSupported = true; } @@ -7019,9 +7033,9 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf if (inputs->device->drive_info.ata_Options.fourtyEightBitAddressFeatureSetSupported && inputs->device->drive_info.ata_Options.generalPurposeLoggingSupported) { - uint8_t data[512] = { 0 }; - int retrySAT16 = ata_Read_Log_Ext(inputs->device, ATA_LOG_DIRECTORY, 0, data, 512, false, 0); - if(retrySAT16 == SUCCESS) + DECLARE_ZERO_INIT_ARRAY(uint8_t, data, 512); + eReturnValues retrySAT16 = ata_Read_Log_Ext(inputs->device, ATA_LOG_DIRECTORY, 0, data, 512, false, 0); + if (retrySAT16 == SUCCESS) { printf("SAT 16-byte passthrough supported, but only for 48bit commands!\n"); satSupported = true; @@ -7040,14 +7054,14 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: This device is not able to pass-through 48 bit (extended) commands!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } if (twelveByteSupported && !sixteenByteSupported) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: ATA28\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.ataPTHacks.ata28BitOnly = true; } @@ -7055,7 +7069,7 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { //if TPSIU worked for identify, we need to try another command, a read, to ensure that it actually works for other commands. //This was added after testing yet another USB bridge that did something odd and different that doesn't really work well - uint8_t *data = C_CAST(uint8_t*, calloc_aligned(inputs->device->drive_info.deviceBlockSize * 1, sizeof(uint8_t), inputs->device->os_info.minimumAlignment)); + uint8_t *data = C_CAST(uint8_t*, safe_calloc_aligned(inputs->device->drive_info.deviceBlockSize * 1, sizeof(uint8_t), inputs->device->os_info.minimumAlignment)); if (data) { bool use48 = inputs->device->drive_info.ata_Options.fourtyEightBitAddressFeatureSetSupported; @@ -7066,28 +7080,28 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf inputs->device->drive_info.passThroughHacks.ataPTHacks.alwaysUseTPSIUForSATPassthrough = true; //Before declaring TPSIU support to be always used, additionally test a read passthrough command to see if that works. - TJE //Using a PIO read command since the DMA test hasn't been performed yet. This is a single sector and should be OK to do at this point. - TJE - int tpsiuRet = ata_Read_Sectors(inputs->device, 0, data, 1, inputs->device->drive_info.deviceBlockSize * 1, use48); + eReturnValues tpsiuRet = ata_Read_Sectors(inputs->device, 0, data, 1, inputs->device->drive_info.deviceBlockSize * 1, use48); if (SUCCESS == tpsiuRet && !does_Sense_Data_Show_Invalid_Field_In_CDB(inputs->device)) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: TPSIU\n");//alwaysUseTPSIUForSATPassthrough - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: TPID\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.ataPTHacks.limitedUseTPSIU = true; inputs->device->drive_info.passThroughHacks.ataPTHacks.alwaysUseTPSIUForSATPassthrough = false; } - safe_Free_aligned(data) + safe_Free_aligned(C_CAST(void**, &data)); } else { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Unable to allocate memory and fully test TPSIU capability.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.ataPTHacks.alwaysUseTPSIUForSATPassthrough = false; } } @@ -7114,27 +7128,27 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: MMPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (inputs->device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } else { set_Console_Colors(true, LIKELY_HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly = true; } //In next tests, need to make sure we actually get response information that makes sense. // Will try SMART, get native max LBA first. Then try sending the drive to standby and checking the power mode, then spinning it up and checking again. // Need to make sure we look for ext RTFRs as well. - + if (!inputs->nocheckConditionTest) { check_Condition_Bit_Test(inputs->device, smartSupported, smartLoggingSupported); @@ -7155,14 +7169,14 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf printf("\n====================================\n"); printf("Comparing ATA and SCSI reported data\n"); printf("====================================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //Here we will compare the reported information by the bridge from SCSI commands to what the ATA Identify data reports. //For MN, SN, FW, check for commonly broken reporting methods. #define PASSTHROUGH_TEST_SCSI_PROD_ID_LEN 17 - char scsiProdID[PASSTHROUGH_TEST_SCSI_PROD_ID_LEN] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, scsiProdID, PASSTHROUGH_TEST_SCSI_PROD_ID_LEN); snprintf(scsiProdID, PASSTHROUGH_TEST_SCSI_PROD_ID_LEN, "%s", scsiInformation->inquiryData.productId); remove_Leading_And_Trailing_Whitespace(scsiProdID); - if (strncmp(scsiProdID, inputs->device->drive_info.bridge_info.childDriveMN, M_Min(16, strlen(scsiProdID))) == 0) + if (strncmp(scsiProdID, inputs->device->drive_info.bridge_info.childDriveMN, M_Min(16, safe_strlen(scsiProdID))) == 0) { printf("\tSAT Compliant product ID reported\n"); } @@ -7170,15 +7184,15 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { set_Console_Colors(true, WARNING_COLOR); printf("\tWARNING: Non-SAT Compliant product ID reported. This may be a \"branded\" product or non-compliant translator.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); printf("\t Checking common non-compliant reporting.\n"); if (strstr(inputs->device->drive_info.bridge_info.childDriveMN, scsiInformation->inquiryData.productId) && strstr(inputs->device->drive_info.bridge_info.childDriveMN, scsiInformation->inquiryData.vendorId)) { //Most likely had the vendor+productID set as the full ATA MN #define PASSTHROUGH_TEST_FULL_MN_LENGTH 42 - char fullMN[PASSTHROUGH_TEST_FULL_MN_LENGTH] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, fullMN, PASSTHROUGH_TEST_FULL_MN_LENGTH); snprintf(fullMN, PASSTHROUGH_TEST_FULL_MN_LENGTH, "%s%s", scsiInformation->inquiryData.vendorId, scsiInformation->inquiryData.productId); - if (strncmp(fullMN, inputs->device->drive_info.bridge_info.childDriveMN, M_Min(strlen(fullMN), strlen(inputs->device->drive_info.bridge_info.childDriveMN))) == 0) + if (strncmp(fullMN, inputs->device->drive_info.bridge_info.childDriveMN, M_Min(safe_strlen(fullMN), safe_strlen(inputs->device->drive_info.bridge_info.childDriveMN))) == 0) { printf("\t\tTranslator put full ATA MN in combination of Vendor and Product ID fields.\n"); } @@ -7188,7 +7202,7 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf printf("\t\tUnknown reporting format.\n"); } } - if (strlen(scsiInformation->vpdData.unitSN)) + if (safe_strlen(scsiInformation->vpdData.unitSN)) { printf("\tChecking unit serial number\n"); if (strstr(scsiInformation->vpdData.unitSN, inputs->device->drive_info.bridge_info.childDriveSN))//using strstr since we remove whitespace from childdriveSN, but not the unit serial number we saved. @@ -7204,36 +7218,36 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { printf("\tNo Unit serial number reported. Skipping this check\n"); } - + if (scsiInformation->vpdData.gotBlockCharacteristicsVPDPage) { //Check rotation rate (if SCSI reported it)...if this doesn't match, check if it is byte swapped and throw a warning. - if(inputs->device->drive_info.IdentifyData.ata.Word217 != 0 && inputs->device->drive_info.IdentifyData.ata.Word217 != scsiInformation->vpdData.blockCharacteristicsData.rotationRate) + if (inputs->device->drive_info.IdentifyData.ata.Word217 != 0 && inputs->device->drive_info.IdentifyData.ata.Word217 != scsiInformation->vpdData.blockCharacteristicsData.rotationRate) { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Rotation rate doesn't Match! Got %" PRIu16 ", expected %" PRIu16 "\n", scsiInformation->vpdData.blockCharacteristicsData.rotationRate, inputs->device->drive_info.IdentifyData.ata.Word217); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); byte_Swap_16(&scsiInformation->vpdData.blockCharacteristicsData.rotationRate); - if(inputs->device->drive_info.IdentifyData.ata.Word217 != scsiInformation->vpdData.blockCharacteristicsData.rotationRate) + if (inputs->device->drive_info.IdentifyData.ata.Word217 != scsiInformation->vpdData.blockCharacteristicsData.rotationRate) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Even after byteswapping, the rotation rate still doesn't match!!!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else { set_Console_Colors(true, WARNING_COLOR); printf("It seems like the RPM was reported without byteswapping it first! Fix this in the translator firmware!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } - + //Check form factor (if SCSI reported it)..if this doesn't match, show a warning since this page was otherwise reported. if (M_Nibble0(inputs->device->drive_info.IdentifyData.ata.Word168) != 0 && M_Nibble0(inputs->device->drive_info.IdentifyData.ata.Word168) != scsiInformation->vpdData.blockCharacteristicsData.formFactor) - { + { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: Formfactor doesn't match! Got %" PRIu8 ", expected %" PRIu8 "\n", scsiInformation->vpdData.blockCharacteristicsData.formFactor, M_Nibble0(inputs->device->drive_info.IdentifyData.ata.Word168)); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } @@ -7266,20 +7280,20 @@ static bool test_SAT_Capabilities(ptrPassthroughTestParams inputs, ptrScsiDevInf { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: WWN was not found in device identification VPD page!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } else { set_Console_Colors(true, WARNING_COLOR); printf("WARNING: Device didn't report device ID VPD page, cannot check for WWN translation!\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } //check block sizes and maxLBA values //Throw a warning that the reverse 4k emulation crap is not useful since we are way past Windows XP at this point. - + //TODO: Based on other SCSI reported information, read the ATA logs that the information should come from to compare and make sure it matches, or is close (>= what SCSI reported) // This should be device statistics, other identify data not checked above, command/feature support, EPC settings, etc @@ -7295,7 +7309,7 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi printf("\n====================================================================\n"); printf("Testing For Legacy ATA Passthrough Support With Known Legacy Methods\n"); printf("====================================================================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); set_Console_Colors(true, WARNING_COLOR); printf("WARNING! Legacy ATA Passthrough methods use vendor unique operation codes!\n"); printf(" Sometimes these operation code will cause problems on devices where\n"); @@ -7313,13 +7327,13 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi delay_Seconds(1); } printf("\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //Now that the users have been warned, it's time to try the different legacy methods until we get a successful identify command through to the device. inputs->device->drive_info.passThroughHacks.passthroughType = ATA_PASSTHROUGH_SAT + 1;//go to the next passthrough type after SAT since SAT is the default since it is the standard. while (inputs->device->drive_info.passThroughHacks.passthroughType != ATA_PASSTHROUGH_UNKNOWN) { - uint8_t identifyData[LEGACY_DRIVE_SEC_SIZE] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(uint8_t, identifyData, LEGACY_DRIVE_SEC_SIZE); if (scsiInformation->inquiryData.peripheralDeviceType == PERIPHERAL_DIRECT_ACCESS_BLOCK_DEVICE) { if (SUCCESS == ata_Identify(inputs->device, identifyData, LEGACY_DRIVE_SEC_SIZE)) @@ -7360,7 +7374,7 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi inputs->device->drive_info.passThroughHacks.ataPTHacks.ata28BitOnly = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: ATA28\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); break; case ATA_PASSTHROUGH_PROLIFIC: printf("Prolific\n"); @@ -7371,7 +7385,7 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi inputs->device->drive_info.passThroughHacks.ataPTHacks.noMultipleModeCommands = true; set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: ATA28\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); break; case ATA_PASSTHROUGH_NEC: printf("NEC\n"); @@ -7383,7 +7397,7 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi printf("Unknown legacy device type! This means the passthrough test code needs updating!\n"); break; } - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); legacyATAPassthroughSupported = true; bool smartSupported = false; bool smartLoggingSupported = false; @@ -7411,13 +7425,13 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: MMPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } else if (inputs->device->drive_info.passThroughHacks.ataPTHacks.singleSectorPIOOnly) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: SPIO\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } //TODO: additional testing here for legacy capabilities! @@ -7426,7 +7440,7 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NOPT\n");//no passthrough available at all - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.passthroughType = ATA_PASSTHROUGH_UNKNOWN; } return legacyATAPassthroughSupported; @@ -7434,7 +7448,7 @@ static bool test_Legacy_ATA_Passthrough(ptrPassthroughTestParams inputs, ptrScsi #define THIRTY_TWO_KB UINT32_C(32768) #define MAX_SCSI_SECTORS_TO_TEST UINT32_C(4096) -static int scsi_Max_Transfer_Length_Test(tDevice *device, uint32_t reportedMax, uint32_t reportedOptimal) +static eReturnValues scsi_Max_Transfer_Length_Test(tDevice *device, uint32_t reportedMax, uint32_t reportedOptimal) { uint32_t maxTestSizeBlocks = MAX_SCSI_SECTORS_TO_TEST; if (reportedMax > 0) @@ -7446,24 +7460,24 @@ static int scsi_Max_Transfer_Length_Test(tDevice *device, uint32_t reportedMax, } } size_t dataBufSize = C_CAST(size_t, maxTestSizeBlocks) * C_CAST(size_t, device->drive_info.deviceBlockSize); - uint8_t *data = C_CAST(uint8_t*, calloc_aligned(dataBufSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *data = C_CAST(uint8_t*, safe_calloc_aligned(dataBufSize, sizeof(uint8_t), device->os_info.minimumAlignment)); set_Console_Colors(true, HEADING_COLOR); printf("\n==================================\n"); printf("Testing SCSI Maximum Transfer Size\n"); printf("==================================\n"); set_Console_Colors(true, NOTE_COLOR); printf("NOTE: This is currently limited to %" PRIu32 " sectors for now\n", maxTestSizeBlocks); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); if (!data) { set_Console_Colors(true, ERROR_COLOR); printf("Fatal error, unable to allocate %" PRIu32 " sectors worth of memory to perform SCSI pass-through test.\n", maxTestSizeBlocks); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return MEMORY_FAILURE; } //start at 1 sector, then double until 32k. From here, increment one sector at a time since most USB devices only handle 32k properly. uint32_t transferLengthSectors = 1; - int readResult = SUCCESS; + eReturnValues readResult = SUCCESS; while (transferLengthSectors <= maxTestSizeBlocks && readResult == SUCCESS) { readResult = scsi_Read(device, 0, false, data, transferLengthSectors * device->drive_info.deviceBlockSize); @@ -7480,8 +7494,8 @@ static int scsi_Max_Transfer_Length_Test(tDevice *device, uint32_t reportedMax, transferLengthSectors += UINT32_C(1); } } - safe_Free_aligned(data) - scsi_Test_Unit_Ready(device, NULL); + safe_Free_aligned(C_CAST(void**, &data)); + scsi_Test_Unit_Ready(device, M_NULLPTR); printf("SCSI Max Transfer Size: %" PRIu32 "B\n", device->drive_info.passThroughHacks.scsiHacks.maxTransferLength); if (reportedMax > 0) { @@ -7495,9 +7509,9 @@ static int scsi_Max_Transfer_Length_Test(tDevice *device, uint32_t reportedMax, } -static int ata_PT_Read(tDevice *device, uint64_t lba, bool async, uint8_t *ptrData, uint32_t dataSize) +static eReturnValues ata_PT_Read(tDevice *device, uint64_t lba, bool async, uint8_t *ptrData, uint32_t dataSize) { - int ret = SUCCESS;//assume success + eReturnValues ret = SUCCESS;//assume success uint16_t sectors = 0; //make sure that the data size is at least logical sector in size if (dataSize < device->drive_info.bridge_info.childDeviceBlockSize) @@ -7748,7 +7762,7 @@ static int ata_PT_Read(tDevice *device, uint64_t lba, bool async, uint8_t *ptrDa } #define MAX_ATA_SECTORS_TO_TEST UINT32_C(4096) -static int ata_Passthrough_Max_Transfer_Length_Test(tDevice *device, uint32_t scsiReportedMax, uint32_t scsiReportedOptimal) +static eReturnValues ata_Passthrough_Max_Transfer_Length_Test(tDevice *device, uint32_t scsiReportedMax, uint32_t scsiReportedOptimal) { uint32_t maxTestSizeBlocks = MAX_ATA_SECTORS_TO_TEST; if (scsiReportedMax > 0) @@ -7760,28 +7774,28 @@ static int ata_Passthrough_Max_Transfer_Length_Test(tDevice *device, uint32_t sc } } size_t dataBufSize = C_CAST(size_t, maxTestSizeBlocks) * C_CAST(size_t, device->drive_info.bridge_info.childDeviceBlockSize); - uint8_t *data = C_CAST(uint8_t*, calloc_aligned(dataBufSize, sizeof(uint8_t), device->os_info.minimumAlignment)); + uint8_t *data = C_CAST(uint8_t*, safe_calloc_aligned(dataBufSize, sizeof(uint8_t), device->os_info.minimumAlignment)); set_Console_Colors(true, HEADING_COLOR); printf("\n=============================================\n"); printf("Testing ATA Pass-through Maximum transfer size\n"); printf("=============================================\n"); set_Console_Colors(true, NOTE_COLOR); printf("NOTE: This is currently limited to %" PRIu32 " sectors for now\n", maxTestSizeBlocks); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); if (!data) { set_Console_Colors(true, ERROR_COLOR); printf("Fatal error, unable to allocate %" PRIu32 " sectors worth of memory to perform ATA pass-through test.\n", maxTestSizeBlocks); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); return MEMORY_FAILURE; } //start at 1 sector, then double until 32k. From here, increment one sector at a time since most USB devices only handle 32k properly. - uint32_t transferLengthSectors = 1; - int readResult = SUCCESS; - while(transferLengthSectors <= maxTestSizeBlocks && readResult == SUCCESS) + uint32_t transferLengthSectors = 1; + eReturnValues readResult = SUCCESS; + while (transferLengthSectors <= maxTestSizeBlocks && readResult == SUCCESS) { readResult = ata_PT_Read(device, 0, false, data, transferLengthSectors * device->drive_info.bridge_info.childDeviceBlockSize); - scsi_Test_Unit_Ready(device, NULL); + scsi_Test_Unit_Ready(device, M_NULLPTR); if (readResult == SUCCESS) { device->drive_info.passThroughHacks.ataPTHacks.maxTransferLength = transferLengthSectors * device->drive_info.bridge_info.childDeviceBlockSize; @@ -7795,8 +7809,8 @@ static int ata_Passthrough_Max_Transfer_Length_Test(tDevice *device, uint32_t sc transferLengthSectors += UINT32_C(1); } } - safe_Free_aligned(data) - scsi_Test_Unit_Ready(device, NULL); + safe_Free_aligned(C_CAST(void**, &data)); + scsi_Test_Unit_Ready(device, M_NULLPTR); printf("ATA Max Transfer Size: %" PRIu32 "B\n", device->drive_info.passThroughHacks.ataPTHacks.maxTransferLength); if (scsiReportedMax > 0) { @@ -7809,9 +7823,9 @@ static int ata_Passthrough_Max_Transfer_Length_Test(tDevice *device, uint32_t sc return SUCCESS; } -int perform_Passthrough_Test(ptrPassthroughTestParams inputs) +eReturnValues perform_Passthrough_Test(ptrPassthroughTestParams inputs) { - int ret = SUCCESS; + eReturnValues ret = SUCCESS; printf("Performing Pass-through test. \n"); printf("If at any point during the test, a crash, a hang, or the device\n"); printf("seems to stop responding to any normal request, save all previously\n"); @@ -7868,7 +7882,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) scsi_Error_Handling_Test(inputs->device, &relativeCommandProcessingPerformance); scsi_Max_Transfer_Length_Test(inputs->device, scsiInformation.vpdData.blockLimitsData.maximumXferLen, scsiInformation.vpdData.blockLimitsData.optimalXferLen); - + //3. Start checking for SAT or VS NVMe passthrough, unless given information to use a different passthrough. //TODO: Make sure to do this only for direct access block devices OR zoned block devices //TODO: Move these passthrough tests to separate functions. @@ -7880,7 +7894,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf("\n==================================================\n"); printf("Checking Vendor Specific NVMe-passthrough commands\n"); printf("==================================================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); //TODO: If given a specific NVMe passthrough type, only test that inputs->device->drive_info.passThroughHacks.passthroughType = NVME_PASSTHROUGH_UNKNOWN; if (inputs->device->drive_info.interface_type != NVME_INTERFACE) @@ -7901,13 +7915,13 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) case NVME_PASSTHROUGH_JMICRON: set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: JMNVME\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); break; case NVME_PASSTHROUGH_ASMEDIA_BASIC: set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: ASMNVMEBASIC\n"); printf("HACK FOUND: IDGLP\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedPassthroughCapabilities = true; inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyController = true; inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyNamespace = true; @@ -7916,7 +7930,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) case NVME_PASSTHROUGH_ASMEDIA: set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: ASMNVME\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); break; default: printf("No NVMe pass-through detected for this device!\n"); @@ -7932,7 +7946,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) { set_Console_Colors(true, ERROR_COLOR); printf("ERROR: SAT Pass-through failed both 12B and 16B CDBs.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); if (inputs->allowLegacyATAPTTest) { test_Legacy_ATA_Passthrough(inputs, &scsiInformation); @@ -7941,7 +7955,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) { set_Console_Colors(true, HACK_COLOR); printf("HACK FOUND: NOPT\n");//no passthrough available at all - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); inputs->device->drive_info.passThroughHacks.passthroughType = ATA_PASSTHROUGH_UNKNOWN; } } @@ -7955,7 +7969,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) { set_Console_Colors(true, NOTE_COLOR); printf("NOTE: Attempting passthrough CDBs for SAT or a vendor unique methods has been disabled and is being skipped.\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } //Finally. Display the results and which hacks were found while testing the device. @@ -7964,7 +7978,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf("\n\n==================\n"); printf("Final Test Results\n"); printf("==================\n"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); printf("SEND THIS INFO BELOW TO seaboard@seagate.com:\n"); //low-level OS device VID/PID/REV as available if (inputs->device->drive_info.adapter_info.infoType != ADAPTER_INFO_UNKNOWN) @@ -8017,7 +8031,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf("\tVendor ID: %s\n", scsiInformation.inquiryData.vendorId); printf("\tProduct ID: %s\n", scsiInformation.inquiryData.productId); printf("\tProduct Rev: %s\n", scsiInformation.inquiryData.productRev); - if (strlen(scsiInformation.vpdData.unitSN) > 0) + if (safe_strlen(scsiInformation.vpdData.unitSN) > 0) { printf("\tUnit Serial Number: %s\n", scsiInformation.vpdData.unitSN); } @@ -8053,7 +8067,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf("\tPlease include the full output from the tool when sending to seaboard@seagate.com\n"); } printf("\tCommand Processing (bad relative to good): %0.02f\n", relativeCommandProcessingPerformance); - + if (inputs->device->drive_info.passThroughHacks.scsiHacks.maxTransferLength < (MAX_SCSI_SECTORS_TO_TEST * inputs->device->drive_info.deviceBlockSize)) { printf("\tSCSI Max Transfer Size: %" PRIu32 "\n", inputs->device->drive_info.passThroughHacks.scsiHacks.maxTransferLength); @@ -8150,7 +8164,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) { set_Console_Colors(true, LIKELY_HACK_COLOR); printf(" NORWZ,"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } if (inputs->device->drive_info.passThroughHacks.scsiHacks.maxTransferLength < (MAX_SCSI_SECTORS_TO_TEST * inputs->device->drive_info.deviceBlockSize)) @@ -8285,7 +8299,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) { set_Console_Colors(true, LIKELY_HACK_COLOR); printf(" SCTSM,");// -please retest to ensure that reading the SCT status log with GPL commands is indeed a necessary hack"); - set_Console_Colors(true, DEFAULT); + set_Console_Colors(true, CONSOLE_COLOR_DEFAULT); } } if (inputs->device->drive_info.passThroughHacks.ataPTHacks.maxTransferLength < (MAX_ATA_SECTORS_TO_TEST * inputs->device->drive_info.bridge_info.childDeviceBlockSize)) @@ -8316,9 +8330,9 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf(" LIMPT,"); if (inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.getLogPage && (inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyGeneric || - (inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyController && inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyNamespace) - ) - ) + (inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyController && inputs->device->drive_info.passThroughHacks.nvmePTHacks.limitedCommandsSupported.identifyNamespace) + ) + ) { printf(" IDGLP,"); } @@ -8355,7 +8369,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf("\tfixed to prevent these hangs, that is the best solution!\n"); ++recommendationCounter; } - #if defined (__linux__) +#if defined (__linux__) if (inputs->device->drive_info.passThroughHacks.passthroughType == ATA_PASSTHROUGH_UNKNOWN) { printf("%" PRIu8 "\tThis device doesn't support passthrough OR this device is being blacklisted\n", recommendationCounter); @@ -8365,7 +8379,7 @@ int perform_Passthrough_Test(ptrPassthroughTestParams inputs) printf("\thandling them correctly in UAS mode.\n"); ++recommendationCounter; } - #endif +#endif if (scsiInformation.vpdData.gotBlockLimitsVPDPage) { //TODO:Check if we hit the maximum in our test: MAX_SCSI_SECTORS_TO_TEST @@ -8466,7 +8480,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); diff --git a/utils/C/openSeaChest/openSeaChest_PowerControl.c b/utils/C/openSeaChest/openSeaChest_PowerControl.c index 9357c93f..e6cd21a8 100644 --- a/utils/C/openSeaChest/openSeaChest_PowerControl.c +++ b/utils/C/openSeaChest/openSeaChest_PowerControl.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,14 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "time_utils.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -31,7 +35,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_PowerControl"; -const char *buildVersion = "3.4.0"; +const char *buildVersion = "3.6.0"; //////////////////////////// // functions to declare // @@ -51,14 +55,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -108,6 +112,7 @@ int32_t main(int argc, char *argv[]) SHOW_POWER_TELEMETRY_VAR REQUEST_POWER_TELEMETRY_MEASUREMENT_VARS SHOW_NVM_POWER_STATES_VAR + PUIS_FEATURE_VARS #if defined (ENABLE_CSMI) CSMI_FORCE_VARS @@ -177,6 +182,7 @@ int32_t main(int argc, char *argv[]) TRANSITION_POWER_STATE_LONG_OPT, SHOW_POWER_TELEMETRY_LONG_OPT, REQUEST_POWER_TELEMETRY_MEASUREMENT_OPTIONS, + PUIS_FEATURE_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -215,11 +221,11 @@ int32_t main(int argc, char *argv[]) if (strcmp(longopts[optionIndex].name, EPC_ENABLED_LONG_OPT_STRING) == 0) { - if (strncmp("enable", optarg, strlen(optarg)) == 0) + if (strcmp("enable", optarg) == 0) { EPC_ENABLED_IDENTIFIER = ENABLE_EPC; } - else if (strncmp("disable", optarg, strlen(optarg)) == 0) + else if (strcmp("disable", optarg) == 0) { EPC_ENABLED_IDENTIFIER = DISABLE_EPC; } @@ -231,12 +237,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, TRANSITION_POWER_STATE_LONG_OPT_STRING) == 0) { - uint64_t temp = UINT64_MAX; - if (get_And_Validate_Integer_Input(C_CAST(const char*, optarg), &temp) && temp < INT32_MAX) - { - TRANSITION_POWER_STATE_TO = C_CAST(int32_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Int32(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &TRANSITION_POWER_STATE_TO)) { print_Error_In_Cmd_Line_Args(TRANSITION_POWER_STATE_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -316,11 +317,7 @@ int32_t main(int argc, char *argv[]) } else { - //set the value to change to (watts) - //use the lf specifier otherwise it thinks it's a standard float and you won't get the right value. - int scanRet = sscanf(optarg, "%lf", &SET_POWER_CONSUMPTION_WATTS_VALUE); -//ctc the check down here needed to change scanRet!=EOF to scanRet==EOF, otherwise command line inputs weren't processed! - if (scanRet == 0 || scanRet == EOF) + if (!get_And_Validate_Double_Input(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_POWER_CONSUMPTION_WATTS_VALUE)) { print_Error_In_Cmd_Line_Args(SET_POWER_CONSUMPTION_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); @@ -329,8 +326,15 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, SET_APM_LEVEL_LONG_OPT_STRING) == 0) { - SET_APM_LEVEL_FLAG = true; - SET_APM_LEVEL_VALUE_FLAG = C_CAST(uint8_t, atoi(optarg)); + if (get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_APM_LEVEL_VALUE_FLAG)) + { + SET_APM_LEVEL_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(SET_APM_LEVEL_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, SEAGATE_POWER_BALANCE_LONG_OPT_STRING) == 0) { @@ -427,7 +431,7 @@ int32_t main(int argc, char *argv[]) print_Error_In_Cmd_Line_Args(SAS_PARTIAL_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - } + } else if (strcmp(longopts[optionIndex].name, SAS_SLUMBER_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "info") == 0) @@ -449,10 +453,14 @@ int32_t main(int argc, char *argv[]) print_Error_In_Cmd_Line_Args(SAS_SLUMBER_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - } + } else if (strcmp(longopts[optionIndex].name, SET_PHY_SAS_PHY_LONG_OPT_STRING) == 0) { - SET_PHY_SAS_PHY_IDENTIFIER = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_PHY_SAS_PHY_IDENTIFIER)) + { + print_Error_In_Cmd_Line_Args(SET_PHY_SAS_PHY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } else if (strcmp(longopts[optionIndex].name, IDLE_A_LONG_OPT_STRING) == 0) { @@ -471,10 +479,45 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - IDLE_A_TIMER_VALID = true; - IDLE_A_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &IDLE_A_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + IDLE_A_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + IDLE_A_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + IDLE_A_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(IDLE_A_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + IDLE_A_TIMER_VALID = true; + IDLE_A_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(IDLE_A_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, IDLE_B_LONG_OPT_STRING) == 0) @@ -494,10 +537,45 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - IDLE_B_TIMER_VALID = true; - IDLE_B_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &IDLE_B_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + IDLE_B_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + IDLE_B_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + IDLE_B_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(IDLE_B_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + IDLE_B_TIMER_VALID = true; + IDLE_B_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(IDLE_B_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, IDLE_C_LONG_OPT_STRING) == 0) @@ -517,10 +595,45 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - IDLE_C_TIMER_VALID = true; - IDLE_C_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &IDLE_C_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + IDLE_C_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + IDLE_C_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + IDLE_C_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(IDLE_C_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + IDLE_C_TIMER_VALID = true; + IDLE_C_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(IDLE_C_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, STANDBY_Z_LONG_OPT_STRING) == 0) @@ -540,10 +653,45 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - STANDBY_Z_TIMER_VALID = true; - STANDBY_Z_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &STANDBY_Z_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + STANDBY_Z_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + STANDBY_Z_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + STANDBY_Z_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(STANDBY_Z_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + STANDBY_Z_TIMER_VALID = true; + STANDBY_Z_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(STANDBY_Z_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, STANDBY_Y_LONG_OPT_STRING) == 0) @@ -563,10 +711,45 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - STANDBY_Y_TIMER_VALID = true; - STANDBY_Y_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &STANDBY_Y_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + STANDBY_Y_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + STANDBY_Y_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + STANDBY_Y_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(STANDBY_Y_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + STANDBY_Y_TIMER_VALID = true; + STANDBY_Y_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(STANDBY_Y_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, LEGACY_IDLE_LONG_OPT_STRING) == 0) @@ -586,10 +769,45 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - LEGACY_IDLE_TIMER_VALID = true; - LEGACY_IDLE_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &LEGACY_IDLE_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + LEGACY_IDLE_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + LEGACY_IDLE_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + LEGACY_IDLE_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(LEGACY_IDLE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + LEGACY_IDLE_TIMER_VALID = true; + LEGACY_IDLE_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(LEGACY_IDLE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, LEGACY_STANDBY_LONG_OPT_STRING) == 0) @@ -609,33 +827,59 @@ int32_t main(int argc, char *argv[]) } else { - //the set function expects time in 100 millisecond units - //Take the input millisecond time and divide it by 100 - LEGACY_STANDBY_TIMER_VALID = true; - LEGACY_STANDBY_POWER_MODE_TIMER = C_CAST(uint32_t, atoi(optarg)) / 100; + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_TIME, &LEGACY_STANDBY_POWER_MODE_TIMER)) + { + if (unit) + { + //convert to milliseconds + if (strcmp(unit, "") == 0 || strcmp(unit, "ms") == 0) + { + //nothing to do as no unit specified or already set milliseconds value + } + else if (strcmp(unit, "s") == 0) + { + LEGACY_STANDBY_POWER_MODE_TIMER *= UINT32_C(1000); + } + else if (strcmp(unit, "m") == 0) + { + LEGACY_STANDBY_POWER_MODE_TIMER *= UINT32_C(60000); + } + else if (strcmp(unit, "h") == 0) + { + LEGACY_STANDBY_POWER_MODE_TIMER *= UINT32_C(3600000); + } + else + { + //invalid unit + print_Error_In_Cmd_Line_Args(LEGACY_STANDBY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + //the set function expects time in 100 millisecond units + //Take the input millisecond time and divide it by 100 + LEGACY_STANDBY_TIMER_VALID = true; + LEGACY_STANDBY_POWER_MODE_TIMER /= 100; + } + else + { + print_Error_In_Cmd_Line_Args(LEGACY_STANDBY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } else if (strcmp(longopts[optionIndex].name, REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT_STRING) == 0) { - uint64_t measurementTime = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char*, optarg), &measurementTime)) + if (get_And_Validate_Integer_Input_Uint16(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &REQUEST_POWER_TELEMETRY_MEASUREMENT_TIME_SECONDS)) { REQUEST_POWER_TELEMETRY_MEASUREMENT_FLAG = true; - if (measurementTime > 65535) - { - REQUEST_POWER_TELEMETRY_MEASUREMENT_TIME_SECONDS = 65535; - } - else - { - REQUEST_POWER_TELEMETRY_MEASUREMENT_TIME_SECONDS = C_CAST(uint16_t, measurementTime); - } } else { print_Error_In_Cmd_Line_Args(REQUEST_POWER_TELEMETRY_MEASUREMENT_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - } + } else if (strcmp(longopts[optionIndex].name, REQUEST_POWER_TELEMETRY_MEASUREMENT_MODE_LONG_OPT_STRING) == 0) { if (strcmp("all", optarg) == 0) @@ -656,6 +900,33 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } + else if (strcmp(longopts[optionIndex].name, PUIS_FEATURE_LONG_OPT_STRING) == 0) + { + PUIS_FEATURE_FLAG = true; + if (strcmp(optarg, "info") == 0) + { + PUIS_FEATURE_INFO_FLAG = true; + } + else if (strcmp(optarg, "enable") == 0) + { + PUIS_FEATURE_STATE_FLAG = true; + PUIS_STATE_VALID_FLAG = true; + } + else if (strcmp(optarg, "disable") == 0) + { + PUIS_FEATURE_STATE_FLAG = false; + PUIS_STATE_VALID_FLAG = true; + } + else if (strcmp(optarg, "spinup") == 0) + { + PUIS_FEATURE_SPINUP_FLAG = true; + } + else + { + print_Error_In_Cmd_Line_Args(PUIS_FEATURE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; @@ -740,9 +1011,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -779,7 +1051,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -876,7 +1148,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -932,6 +1204,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -984,6 +1258,7 @@ int32_t main(int argc, char *argv[]) || SHOW_POWER_TELEMETRY_FLAG || REQUEST_POWER_TELEMETRY_MEASUREMENT_FLAG || SHOW_NVM_POWER_STATES + || PUIS_FEATURE_FLAG )) { utility_Usage(true); @@ -992,7 +1267,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1037,7 +1312,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -1085,11 +1360,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -1113,7 +1388,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -1155,7 +1430,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1180,7 +1455,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1220,6 +1495,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1420,11 +1704,39 @@ int32_t main(int argc, char *argv[]) } } + if (PUIS_FEATURE_FLAG && PUIS_FEATURE_SPINUP_FLAG) + { + switch (puis_Spinup(&deviceList[deviceIter])) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\nSuccessfully performed PUIS spinup command\n"); + printf("\nHint:Use --checkPowerMode option to check the new Power State.\n\n"); + } + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("PUIS spinup command is not supported on this device.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to perform the PUIS spinup command\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (SHOW_NVM_POWER_STATES) { nvmeSupportedPowerStates ps; memset(&ps, 0, sizeof(nvmeSupportedPowerStates)); - switch(get_NVMe_Power_States(&deviceList[deviceIter], &ps)) + switch (get_NVMe_Power_States(&deviceList[deviceIter], &ps)) { case SUCCESS: print_NVM_Power_States(&ps); @@ -1803,9 +2115,9 @@ int32_t main(int argc, char *argv[]) } else { - int idleRet = SUCCESS; - char modeChangeStrSuccess[LEGACY_POWER_MODE_CHANGE_STR_LEN] = { 0 }; - char modeChangeStrNotSuccess[LEGACY_POWER_MODE_CHANGE_STR_LEN] = { 0 }; + eReturnValues idleRet = SUCCESS; + DECLARE_ZERO_INIT_ARRAY(char, modeChangeStrSuccess, LEGACY_POWER_MODE_CHANGE_STR_LEN); + DECLARE_ZERO_INIT_ARRAY(char, modeChangeStrNotSuccess, LEGACY_POWER_MODE_CHANGE_STR_LEN); switch (LEGACY_IDLE_STATE) { case POWER_MODE_STATE_ENABLE: @@ -1901,9 +2213,9 @@ int32_t main(int argc, char *argv[]) { if (deviceList[deviceIter].drive_info.drive_type == SCSI_DRIVE) { - int standbyRet = SUCCESS; - char modeChangeStrSuccess[LEGACY_POWER_MODE_CHANGE_STR_LEN] = { 0 }; - char modeChangeStrNotSuccess[LEGACY_POWER_MODE_CHANGE_STR_LEN] = { 0 }; + eReturnValues standbyRet = SUCCESS; + DECLARE_ZERO_INIT_ARRAY(char, modeChangeStrSuccess, LEGACY_POWER_MODE_CHANGE_STR_LEN); + DECLARE_ZERO_INIT_ARRAY(char, modeChangeStrNotSuccess, LEGACY_POWER_MODE_CHANGE_STR_LEN); switch (LEGACY_STANDBY_STATE) { case POWER_MODE_STATE_ENABLE: @@ -1966,11 +2278,116 @@ int32_t main(int argc, char *argv[]) } } + if (PUIS_FEATURE_FLAG && !PUIS_FEATURE_SPINUP_FLAG) + { + //handle all other PUIS feature options as spinup is handled above with other powerstate transitioning commands. + if (PUIS_FEATURE_INFO_FLAG) + { + puisInfo info; + memset(&info, 0, sizeof(puisInfo)); + switch (get_PUIS_Info(&deviceList[deviceIter], &info)) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("===PUIS Info===\n"); + if (info.puisSupported) + { + if (info.puisEnabled) + { + printf("\tPUIS is supported and enabled\n"); + } + else + { + printf("\tPUIS is supported\n"); + } + if (info.spinupCommandRequired) + { + printf("\tSpin-Up command is required for medium access.\n"); + } + else + { + printf("\tAutomatic spin-up as needed for medium access.\n"); + } + } + else + { + printf("\tPUIS is not supported on this device.\n"); + } + } + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("PUIS is not available on this device type!\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Failed to get PUIS info from this device\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (PUIS_STATE_VALID_FLAG) + { + switch (enable_Disable_PUIS_Feature(&deviceList[deviceIter], PUIS_FEATURE_STATE_FLAG)) + { + case SUCCESS: + if (VERBOSITY_QUIET < toolVerbosity) + { + if (PUIS_FEATURE_STATE_FLAG) + { + printf("PUIS feature successfully enabled!\n"); + } + else + { + printf("PUIS feature successfully disabled!\n"); + } + } + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + if (PUIS_FEATURE_STATE_FLAG) + { + printf("Enabling PUIS feature not supported on this device.\n"); + } + else + { + printf("Disabling PUIS feature not supported on this device.\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + if (PUIS_FEATURE_STATE_FLAG) + { + printf("Failed to enable PUIS feature!\n"); + } + else + { + printf("Failed to disable PUIS feature!\n"); + printf("If PUIS is enabled with a jumper, it cannot be disabled with this command!\n"); + printf("Remove the PUIS jumper to disable the feature in this case.\n"); + } + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + } + if (SHOW_EPC_SETTINGS_FLAG) { epcSettings deviceEPCSettings; memset(&deviceEPCSettings, 0, sizeof(epcSettings)); - switch(get_EPC_Settings(&deviceList[deviceIter], &deviceEPCSettings)) + switch (get_EPC_Settings(&deviceList[deviceIter], &deviceEPCSettings)) { case SUCCESS: print_EPC_Settings(&deviceList[deviceIter], &deviceEPCSettings); @@ -2020,7 +2437,7 @@ int32_t main(int argc, char *argv[]) if (SET_POWER_CONSUMPTION_FLAG) { - int pcRet = SUCCESS; + eReturnValues pcRet = SUCCESS; if (SET_POWER_CONSUMPTION_ACTIVE_LEVEL_VALUE == PC_ACTIVE_LEVEL_IDENTIFIER) { pcRet = map_Watt_Value_To_Power_Consumption_Identifier(&deviceList[deviceIter], SET_POWER_CONSUMPTION_WATTS_VALUE, &SET_POWER_CONSUMPTION_VALUE); @@ -2065,9 +2482,9 @@ int32_t main(int argc, char *argv[]) } } - if(SET_APM_LEVEL_FLAG) + if (SET_APM_LEVEL_FLAG) { - switch(set_APM_Level(&deviceList[deviceIter], SET_APM_LEVEL_VALUE_FLAG)) + switch (set_APM_Level(&deviceList[deviceIter], SET_APM_LEVEL_VALUE_FLAG)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -2121,29 +2538,29 @@ int32_t main(int argc, char *argv[]) if (SHOW_APM_LEVEL_FLAG) { - switch(get_APM_Level(&deviceList[deviceIter], &SHOW_APM_LEVEL_VALUE_FLAG)) + switch (get_APM_Level(&deviceList[deviceIter], &SHOW_APM_LEVEL_VALUE_FLAG)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Current APM Level is %"PRIu8" (", SHOW_APM_LEVEL_VALUE_FLAG); - if(SHOW_APM_LEVEL_VALUE_FLAG == 0x01) + printf("Current APM Level is %" PRIu8 " (", SHOW_APM_LEVEL_VALUE_FLAG); + if (SHOW_APM_LEVEL_VALUE_FLAG == 0x01) { printf("Minimum power consumption with Standby mode"); } - else if(SHOW_APM_LEVEL_VALUE_FLAG >= 0x02 && SHOW_APM_LEVEL_VALUE_FLAG <= 0x7F) + else if (SHOW_APM_LEVEL_VALUE_FLAG >= 0x02 && SHOW_APM_LEVEL_VALUE_FLAG <= 0x7F) { printf("Intermediate power management with Standby mode"); } - else if(SHOW_APM_LEVEL_VALUE_FLAG == 0x80) + else if (SHOW_APM_LEVEL_VALUE_FLAG == 0x80) { printf("Minimum power consumption without Standby mode"); } - else if(SHOW_APM_LEVEL_VALUE_FLAG >= 0x81 && SHOW_APM_LEVEL_VALUE_FLAG <= 0xFD) + else if (SHOW_APM_LEVEL_VALUE_FLAG >= 0x81 && SHOW_APM_LEVEL_VALUE_FLAG <= 0xFD) { printf("Intermediate power management without Standby mode"); } - else if(SHOW_APM_LEVEL_VALUE_FLAG == 0xFE) + else if (SHOW_APM_LEVEL_VALUE_FLAG == 0xFE) { printf("Maximum Performance"); } @@ -2236,7 +2653,8 @@ int32_t main(int argc, char *argv[]) } else { - bool powerBalanceSupported = false, powerBalanceEnabled = false; + bool powerBalanceSupported = false; + bool powerBalanceEnabled = false; switch (seagate_Get_Power_Balance(&deviceList[deviceIter], &powerBalanceSupported, &powerBalanceEnabled)) { case SUCCESS: @@ -2314,7 +2732,8 @@ int32_t main(int argc, char *argv[]) } if (SATA_DIPM_INFO_FLAG) { - bool dipmSupported = false, dipmEnabled = false; + bool dipmSupported = false; + bool dipmEnabled = false; switch (sata_Get_Device_Initiated_Interface_Power_State_Transitions(&deviceList[deviceIter], &dipmSupported, &dipmEnabled)) { case SUCCESS: @@ -2391,7 +2810,8 @@ int32_t main(int argc, char *argv[]) if (SATA_DAPS_INFO_FLAG) { - bool dapsSupported = false, dapsEnabled = false; + bool dapsSupported = false; + bool dapsEnabled = false; switch (sata_Get_Device_Automatic_Partioan_To_Slumber_Transtisions(&deviceList[deviceIter], &dapsSupported, &dapsEnabled)) { case SUCCESS: @@ -2435,7 +2855,7 @@ int32_t main(int argc, char *argv[]) if (SAS_PARTIAL_FLAG || SAS_SLUMBER_FLAG) { #define SEACHEST_POWERCONTROL_PARTIAL_SLUMBER_STRING_LENGTH 40 - char partialSlumberString[SEACHEST_POWERCONTROL_PARTIAL_SLUMBER_STRING_LENGTH] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, partialSlumberString, SEACHEST_POWERCONTROL_PARTIAL_SLUMBER_STRING_LENGTH); if (SAS_PARTIAL_FLAG && SAS_SLUMBER_FLAG) { snprintf(partialSlumberString, SEACHEST_POWERCONTROL_PARTIAL_SLUMBER_STRING_LENGTH, "SAS Partial & Slumber"); @@ -2479,7 +2899,7 @@ int32_t main(int argc, char *argv[]) if (SAS_PARTIAL_INFO_FLAG || SAS_SLUMBER_INFO_FLAG) { - int result = SUCCESS; + eReturnValues result = SUCCESS; uint8_t phyListSize = 1; if (SET_PHY_SAS_PHY_IDENTIFIER == 0xFF) { @@ -2487,7 +2907,7 @@ int32_t main(int argc, char *argv[]) } if (SUCCESS == result) { - ptrSasEnhPhyControl phyData = C_CAST(ptrSasEnhPhyControl, calloc(phyListSize, sizeof(sasEnhPhyControl))); + ptrSasEnhPhyControl phyData = C_CAST(ptrSasEnhPhyControl, safe_calloc(phyListSize, sizeof(sasEnhPhyControl))); if (phyData) { //get the information needed, then show it @@ -2512,7 +2932,7 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; break; } - safe_Free(phyData); + safe_free_sasEnhPhyControl(&phyData); } else { @@ -2554,9 +2974,9 @@ int32_t main(int argc, char *argv[]) if (VERBOSITY_QUIET < toolVerbosity) { printf("Successfully requested a power measurement.\n"); - time_t currentTime = time(NULL); + time_t currentTime = time(M_NULLPTR); time_t futureTime = get_Future_Date_And_Time(currentTime, REQUEST_POWER_TELEMETRY_MEASUREMENT_TIME_SECONDS); - char timeFormat[TIME_STRING_LENGTH] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, timeFormat, TIME_STRING_LENGTH); printf("\n\tCurrent Time: %s\n", get_Current_Time_String(C_CAST(const time_t*, ¤tTime), timeFormat, TIME_STRING_LENGTH)); memset(timeFormat, 0, TIME_STRING_LENGTH); printf("\tEstimated completion Time : %s", get_Current_Time_String(C_CAST(const time_t*, &futureTime), timeFormat, TIME_STRING_LENGTH)); @@ -2643,7 +3063,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -2696,7 +3116,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -2757,6 +3177,7 @@ void utility_Usage(bool shortUsage) print_Disable_APM_Help(shortUsage); print_DAPS_Help(shortUsage); print_DIPM_Help(shortUsage); + print_PUIS_Feature_Help(shortUsage); print_Set_APM_Level_Help(shortUsage); print_Show_APM_Level_Help(shortUsage); //SAS Only Options diff --git a/utils/C/openSeaChest/openSeaChest_Raw.c b/utils/C/openSeaChest/openSeaChest_Raw.c new file mode 100644 index 00000000..8394b850 --- /dev/null +++ b/utils/C/openSeaChest/openSeaChest_Raw.c @@ -0,0 +1,2134 @@ +// +// Do NOT modify or remove this copyright and license +// +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// +// This software is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// ****************************************************************************************** +// +// \file openSeaChest_Raw.c Binary command line that sends raw TFRs or CDBs + +////////////////////// +// Included files // +////////////////////// +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "getopt.h" +#include "EULA.h" +#include "openseachest_util_options.h" +#include "operations.h" +#include "drive_info.h" +//////////////////////// +// Global Variables // +//////////////////////// +const char* util_name = "openSeaChest_Raw"; +const char* buildVersion = "0.9.0"; + +//////////////////////////// +// functions to declare // +//////////////////////////// +static void utility_Usage(bool shortUsage); +//----------------------------------------------------------------------------- +// +// main() +// +//! \brief Description: main function that runs and decides what to do based on the passed in args +// +// Entry: +//! \param argc = +//! \param argv = +//! +// Exit: +//! \return exitCode = error code returned by the application +// +//----------------------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + ///////////////// + // Variables // + ///////////////// + //common utility variables + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; + DEVICE_UTIL_VARS + DEVICE_INFO_VAR + SAT_INFO_VAR + LICENSE_VAR + ECHO_COMMAND_LINE_VAR + SCAN_FLAG_VAR + NO_BANNER_VAR + AGRESSIVE_SCAN_FLAG_VAR + SHOW_BANNER_VAR + SHOW_HELP_VAR + TEST_UNIT_READY_VAR + FAST_DISCOVERY_VAR + MODEL_MATCH_VARS + FW_MATCH_VARS + CHILD_MODEL_MATCH_VARS + CHILD_FW_MATCH_VARS + ONLY_SEAGATE_VAR + FORCE_DRIVE_TYPE_VARS + ENABLE_LEGACY_PASSTHROUGH_VAR + //scan output flags + SCAN_FLAGS_UTIL_VARS + //tool specific flags + RAW_TFR_SIZE_VAR + RAW_TFR_VARS + RAW_TFR_PROTOCOL_VAR + RAW_TFR_XFER_LENGTH_LOCATION_VAR + RAW_TFR_CHECK_CONDITION_VAR + RAW_DATA_LEN_VARS + RAW_DATA_DIRECTION_VAR + RAW_TIMEOUT_VAR + RAW_OUTPUT_FILE_VARS + RAW_INPUT_FILE_VARS + RAW_INPUT_FILE_OFFSET_VAR + RAW_TFR_BYTE_BLOCK_VAR + RAW_CDB_LEN_VAR + RAW_CDB_ARRAY_VAR +#if defined (ENABLE_CSMI) + CSMI_FORCE_VARS + CSMI_VERBOSE_VAR +#endif + + int args = 0; + int argIndex = 0; + int optionIndex = 0; + + struct option longopts[] = { + //common command line options + DEVICE_LONG_OPT, + HELP_LONG_OPT, + DEVICE_INFO_LONG_OPT, + SAT_INFO_LONG_OPT, + USB_CHILD_INFO_LONG_OPT, + SCAN_LONG_OPT, + NO_BANNER_OPT, + AGRESSIVE_SCAN_LONG_OPT, + SCAN_FLAGS_LONG_OPT, + VERSION_LONG_OPT, + VERBOSE_LONG_OPT, + QUIET_LONG_OPT, + LICENSE_LONG_OPT, + ECHO_COMMAND_LIN_LONG_OPT, + TEST_UNIT_READY_LONG_OPT, + FAST_DISCOVERY_LONG_OPT, + ONLY_SEAGATE_LONG_OPT, + MODEL_MATCH_LONG_OPT, + FW_MATCH_LONG_OPT, + CHILD_MODEL_MATCH_LONG_OPT, + CHILD_FW_MATCH_LONG_OPT, + FORCE_DRIVE_TYPE_LONG_OPTS, + ENABLE_LEGACY_PASSTHROUGH_LONG_OPT, +#if defined (ENABLE_CSMI) + CSMI_VERBOSE_LONG_OPT, + CSMI_FORCE_LONG_OPTS, +#endif + //tool specific options go here + RAW_CDB_LEN_LONG_OPT, + RAW_CDB_ARRAY_LONG_OPT, + RAW_TFR_SIZE_LONG_OPT, + RAW_TFR_REGITER_LONG_OPTS, + RAW_TFR_PROTOCOL_LONG_OPT, + RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT, + RAW_TFR_CHECK_CONDITION_LONG_OPT, + RAW_TFR_BYTE_BLOCK_LONG_OPT, + RAW_DATA_LEN_LONG_OPT, + RAW_DATA_DIRECTION_LONG_OPT, + RAW_TIMEOUT_LONG_OPT, + RAW_OUTPUT_FILE_LONG_OPT, + RAW_INPUT_FILE_LONG_OPT, + LONG_OPT_TERMINATOR + }; + + eVerbosityLevels toolVerbosity = VERBOSITY_DEFAULT; + +#if defined (UEFI_C_SOURCE) + //NOTE: This is a BSD function used to ensure the program name is set correctly for warning or error functions. + // This is not necessary on most modern systems other than UEFI. + // This is not used in linux so that we don't depend on libbsd + // Update the above #define check if we port to another OS that needs this to be done. + setprogname(util_name); +#endif + + //////////////////////// + // Argument Parsing // + //////////////////////// + if (argc < 2) + { + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + utility_Usage(true); + printf("\n"); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + //get options we know we need + while (1) //changed to while 1 in order to parse multiple options when longs options are involved + { + args = getopt_long(argc, argv, "d:hisSF:Vv:q%:", longopts, &optionIndex); + if (args == -1) + { + break; + } + //printf("Parsing arg <%u>\n", args); + switch (args) + { + case 0: + //parse long options that have no short option and required arguments here + if (strcmp(longopts[optionIndex].name, RAW_CDB_ARRAY_LONG_OPT_STRING) == 0) + { + char* saveptr = M_NULLPTR; + rsize_t duplen = 0; + char* dupoptarg = strdup(optarg); + char* token = M_NULLPTR; + uint8_t count = 0; + bool errorInCL = false; + if (dupoptarg) + { + duplen = safe_strlen(dupoptarg); + token = common_String_Token(dupoptarg, &duplen, ",", &saveptr); + } + else + { + errorInCL = true; + } + while (token && !errorInCL && count < UINT8_MAX) + { + uint8_t value = 0; + if (get_And_Validate_Integer_Input_Uint8(token, M_NULLPTR, ALLOW_UNIT_NONE, &value)) + { + RAW_CDB_ARRAY[count] = value; + ++count; + token = common_String_Token(M_NULLPTR, &duplen, ",", &saveptr); + } + else + { + errorInCL = true; + } + } + safe_free(&dupoptarg); + if (errorInCL) + { + print_Error_In_Cmd_Line_Args(RAW_CDB_ARRAY_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_CDB_LEN_LONG_OPT_STRING) == 0) + { + //set the cdblength + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_CDB_LEN_FLAG)) + { + print_Error_In_Cmd_Line_Args(RAW_CDB_LEN_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_SIZE_LONG_OPT_STRING) == 0) + { + if (strcmp(optarg, "complete") == 0) + { + RAW_TFR_SIZE_FLAG = 0xFF; + } + else + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_SIZE_FLAG)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_SIZE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_COMMAND_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_COMMAND)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_COMMAND_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_FEATURE_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_FEATURE)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_FEATURE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_FEATURE_EXT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_FEATURE_EXT)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_FEATURE_EXT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_FEATURE_FULL_LONG_OPT_STRING) == 0) + { + uint16_t fullfeat = 0; + if (!get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &fullfeat)) + { + RAW_TFR_FEATURE = M_Byte0(fullfeat); + RAW_TFR_FEATURE_EXT = M_Byte1(fullfeat); + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_FEATURE_FULL_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_LOW_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_LBA_LOW)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_LOW_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_MID_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_LBA_MID)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_MID_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_HIGH_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_LBA_HIGH)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_HIGH_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_LOW_EXT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_LBA_LOW_EXT)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_LOW_EXT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_MID_EXT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_LBA_MID_EXT)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_MID_EXT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_HIGH_EXT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_LBA_HIGH_EXT)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_HIGH_EXT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_FULL_LONG_OPT_STRING) == 0) + { + uint64_t fullLBA = 0; + if (get_And_Validate_Integer_Input_Uint64(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &fullLBA) && fullLBA <= MAX_48_BIT_LBA) + { + RAW_TFR_LBA_LOW = M_Byte0(fullLBA); + RAW_TFR_LBA_MID = M_Byte1(fullLBA); + RAW_TFR_LBA_HIGH = M_Byte2(fullLBA); + RAW_TFR_LBA_LOW_EXT = M_Byte3(fullLBA); + RAW_TFR_LBA_MID_EXT = M_Byte4(fullLBA); + RAW_TFR_LBA_HIGH_EXT = M_Byte5(fullLBA); + //TODO: On a 28bit command, we may need to set the lower nibble of device/head for the high bits of the LBA value + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_LBA_FULL_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_DEVICE_HEAD_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_DEVICE_HEAD)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_DEVICE_HEAD_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_LBA_MODE_BIT_LONG_OPT_STRING) == 0) + { + RAW_TFR_DEVICE_HEAD |= LBA_MODE_BIT; + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_SECTOR_COUNT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_SECTOR_COUNT)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_SECTOR_COUNT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_SECTOR_COUNT_EXT)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_SECTOR_COUNT_EXT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT_STRING) == 0) + { + uint16_t fullseccnt = 0; + if (get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &fullseccnt)) + { + RAW_TFR_SECTOR_COUNT = M_Byte0(fullseccnt); + RAW_TFR_SECTOR_COUNT_EXT = M_Byte1(fullseccnt); + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_SECTOR_COUNT_FULL_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_ICC_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_ICC)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_ICC_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_AUX1_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_AUX1)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_AUX1_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_AUX2_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_AUX2)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_AUX2_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_AUX3_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_AUX3)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_AUX3_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_AUX4_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TFR_AUX4)) + { + print_Error_In_Cmd_Line_Args(RAW_TFR_AUX4_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_AUX_FULL_LONG_OPT_STRING) == 0) + { + uint32_t fullaux = 0; + if (get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &fullaux)) + { + RAW_TFR_AUX1 = M_Byte0(fullaux); + RAW_TFR_AUX2 = M_Byte1(fullaux); + RAW_TFR_AUX3 = M_Byte2(fullaux); + RAW_TFR_AUX4 = M_Byte3(fullaux); + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_AUX4_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_PROTOCOL_LONG_OPT_STRING) == 0) + { + //set the protocol + if (strcmp(optarg, "pio") == 0 || strcmp(optarg, "PIO") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_PIO); + } + else if (strcmp(optarg, "dma") == 0 || strcmp(optarg, "DMA") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_DMA); + } + else if (strcmp(optarg, "udma") == 0 || strcmp(optarg, "UDMA") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_UDMA); + } + else if (strcmp(optarg, "fpdma") == 0 || strcmp(optarg, "FPDMA") == 0 || strcmp(optarg, "ncq") == 0 || strcmp(optarg, "NCQ") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_DMA_FPDMA); + } + else if (strcmp(optarg, "nodata") == 0 || strcmp(optarg, "NODATA") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_NO_DATA); + } + else if (strcmp(optarg, "reset") == 0 || strcmp(optarg, "RESET") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_DEV_RESET); + } + else if (strcmp(optarg, "dmaque") == 0 || strcmp(optarg, "DMAQUE") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_DMA_QUE); + } + else if (strcmp(optarg, "diag") == 0 || strcmp(optarg, "DIAG") == 0) + { + RAW_TFR_PROTOCOL = C_CAST(int, ATA_PROTOCOL_DEV_DIAG); + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_PROTOCOL_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT_STRING) == 0) + { + if (strcmp(optarg, "sectorCount") == 0) + { + RAW_TFR_XFER_LENGTH_LOCATION = ATA_PT_LEN_SECTOR_COUNT; + } + else if (strcmp(optarg, "feature") == 0) + { + RAW_TFR_XFER_LENGTH_LOCATION = ATA_PT_LEN_FEATURES_REGISTER; + } + else if (strcmp(optarg, "tpsiu") == 0) + { + RAW_TFR_XFER_LENGTH_LOCATION = ATA_PT_LEN_TPSIU; + } + else if (strcmp(optarg, "nodata") == 0) + { + RAW_TFR_XFER_LENGTH_LOCATION = ATA_PT_LEN_NO_DATA; + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TFR_BYTE_BLOCK_LONG_OPT_STRING) == 0) + { + if (strcmp(optarg, "512") == 0) + { + RAW_TFR_BYTE_BLOCK = 512; + } + else if (strcmp(optarg, "logical") == 0) + { + RAW_TFR_BYTE_BLOCK = UINT8_MAX; + } + else if (strcmp(optarg, "bytes") == 0) + { + RAW_TFR_BYTE_BLOCK = 1; + } + else if (strcmp(optarg, "nodata") == 0) + { + RAW_TFR_BYTE_BLOCK = 0; + } + else + { + print_Error_In_Cmd_Line_Args(RAW_TFR_BYTE_BLOCK_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_DATA_LEN_LONG_OPT_STRING) == 0) + { + char* unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint32(optarg, &unit, ALLOW_UNIT_DATASIZE, &RAW_DATA_LEN_FLAG)) + { + //Check to see if any units were specified, otherwise assume LBAs + uint32_t multiplier = 1; + if (unit) + { + if (strcmp(unit, "") == 0) + { + RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG = true; + } + else if (strcmp(unit, "BLOCKS") == 0 || strcmp(unit, "SECTORS") == 0) + { + //they specified blocks. For log transfers this means a number of 512B sectors + multiplier = LEGACY_DRIVE_SEC_SIZE; + } + else if (strcmp(unit, "KB") == 0) + { + multiplier = UINT32_C(1000); + } + else if (strcmp(unit, "KiB") == 0) + { + multiplier = UINT32_C(1024); + } + else if (strcmp(unit, "MB") == 0) + { + multiplier = UINT32_C(1000000); + } + else if (strcmp(unit, "MiB") == 0) + { + multiplier = UINT32_C(1048576); + } + else if (strcmp(unit, "GB") == 0) + { + multiplier = UINT32_C(1000000000); + } + else if (strcmp(unit, "GiB") == 0) + { + multiplier = UINT32_C(1073741824); + } + else + { + print_Error_In_Cmd_Line_Args(RAW_DATA_LEN_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + RAW_DATA_LEN_FLAG *= multiplier; + } + else + { + print_Error_In_Cmd_Line_Args(RAW_DATA_LEN_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_DATA_DIRECTION_LONG_OPT_STRING) == 0) + { + if (strcmp(optarg, "in") == 0) + { + RAW_DATA_DIRECTION_FLAG = XFER_DATA_IN; + } + else if (strcmp(optarg, "out") == 0) + { + RAW_DATA_DIRECTION_FLAG = XFER_DATA_OUT; + } + else if (strcmp(optarg, "none") == 0) + { + RAW_DATA_DIRECTION_FLAG = XFER_NO_DATA; + } + //all other inputs are invalid for now + else + { + print_Error_In_Cmd_Line_Args(RAW_DATA_DIRECTION_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_TIMEOUT_LONG_OPT_STRING) == 0) + { + if (!get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &RAW_TIMEOUT_FLAG)) + { + print_Error_In_Cmd_Line_Args(RAW_TIMEOUT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, RAW_OUTPUT_FILE_LONG_OPT_STRING) == 0) + { + //open the file later + RAW_OUTPUT_FILE_NAME_FLAG = optarg; + } + else if (strcmp(longopts[optionIndex].name, RAW_INPUT_FILE_LONG_OPT_STRING) == 0) + { + //open the file later + RAW_INPUT_FILE_NAME_FLAG = optarg; + } + else if (strcmp(longopts[optionIndex].name, RAW_INPUT_FILE_OFFSET_LONG_OPT_STRING) == 0) + { + //set the offset to read the file at + //set the raw data length - but check the units first! + char* unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Int64(optarg, &unit, ALLOW_UNIT_DATASIZE, &RAW_INPUT_FILE_OFFSET_FLAG)) + { + int64_t multiplier = 1; + if (strstr(optarg, "BLOCKS")) + { + //the user specified the number as a number of logical blocks, so adjust this after we know the device logical block size + RAW_INPUT_OFFSET_ADJUST_BY_BLOCKS_FLAG = true; + } + else if (strstr(optarg, "KB")) + { + multiplier = 1000; + } + else if (strstr(optarg, "KiB")) + { + multiplier = 1024; + } + else if (strstr(optarg, "MB")) + { + multiplier = 1000000; + } + else if (strstr(optarg, "MiB")) + { + multiplier = 1048576; + } + else if (strstr(optarg, "GB")) + { + multiplier = 1000000000; + } + else if (strstr(optarg, "GiB")) + { + multiplier = 1073741824; + } + else + { + print_Error_In_Cmd_Line_Args(RAW_INPUT_FILE_OFFSET_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + RAW_INPUT_FILE_OFFSET_FLAG = RAW_INPUT_FILE_OFFSET_FLAG * multiplier; + } + else + { + print_Error_In_Cmd_Line_Args(RAW_INPUT_FILE_OFFSET_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) + { + MODEL_MATCH_FLAG = true; + snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) + { + FW_MATCH_FLAG = true; + snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) + { + CHILD_MODEL_MATCH_FLAG = true; + snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); + } + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) + { + CHILD_FW_MATCH_FLAG = true; + snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); + } + break; + case ':'://missing required argument + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + switch (optopt) + { + case 0: + //check long options for missing arguments + break; + case DEVICE_SHORT_OPT: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify a device handle\n"); + } + return UTIL_EXIT_INVALID_DEVICE_HANDLE; + case VERBOSE_SHORT_OPT: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify a verbosity level. 0 - 4 are the valid levels\n"); + } + break; + case SCAN_FLAGS_SHORT_OPT: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify which scan options flags you want to use.\n"); + } + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Option %c requires an argument\n", optopt); + } + utility_Usage(true); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(exitCode); + } + break; + case DEVICE_SHORT_OPT: //device + if (0 != parse_Device_Handle_Argument(optarg, &RUN_ON_ALL_DRIVES, &USER_PROVIDED_HANDLE, &DEVICE_LIST_COUNT, &HANDLE_LIST)) + { + //Free any memory allocated so far, then exit. + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(255); + } + break; + case DEVICE_INFO_SHORT_OPT: //device information + DEVICE_INFO_FLAG = true; + break; + case SCAN_SHORT_OPT: //scan + SCAN_FLAG = true; + break; + case AGRESSIVE_SCAN_SHORT_OPT: + AGRESSIVE_SCAN_FLAG = true; + break; + case VERSION_SHORT_OPT: + SHOW_BANNER_FLAG = true; + break; + case VERBOSE_SHORT_OPT: //verbose + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) + { + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + break; + case QUIET_SHORT_OPT: //quiet mode + toolVerbosity = VERBOSITY_QUIET; + break; + case SCAN_FLAGS_SHORT_OPT://scan flags + get_Scan_Flags(&SCAN_FLAGS, optarg); + break; + case '?': //unknown option + printf("%s: Unable to parse %s command line option\nPlease use --%s for more information.\n", util_name, argv[optind - 1], HELP_LONG_OPT_STRING); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + case 'h': //help + SHOW_HELP_FLAG = true; + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + utility_Usage(false); + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n"); + } + exit(UTIL_EXIT_NO_ERROR); + default: + break; + } + } + + atexit(print_Final_newline); + + if (ECHO_COMMAND_LINE_FLAG) + { + int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) + for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) + { + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) + { + continue; + } + printf("%s ", argv[commandLineIter]); + } + printf("\n"); + } + + if ((VERBOSITY_QUIET < toolVerbosity) && !NO_BANNER_FLAG) + { + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + } + + if (SHOW_BANNER_FLAG) + { + utility_Full_Version_Info(util_name, buildVersion, OPENSEA_TRANSPORT_MAJOR_VERSION, OPENSEA_TRANSPORT_MINOR_VERSION, OPENSEA_TRANSPORT_PATCH_VERSION, OPENSEA_COMMON_VERSION, OPENSEA_OPERATION_VERSION); + } + + if (LICENSE_FLAG) + { + print_EULA_To_Screen(); + } + + if (SCAN_FLAG || AGRESSIVE_SCAN_FLAG) + { + if (!is_Running_Elevated()) + { + print_Elevated_Privileges_Text(); + } + unsigned int scanControl = DEFAULT_SCAN; + if (AGRESSIVE_SCAN_FLAG) + { + scanControl |= AGRESSIVE_SCAN; + } +#if defined (__linux__) + if (SCAN_FLAGS.scanSD) + { + scanControl |= SD_HANDLES; + } + if (SCAN_FLAGS.scanSDandSG) + { + scanControl |= SG_TO_SD; + } +#endif + //set the drive types to show (if none are set, the lower level code assumes we need to show everything) + if (SCAN_FLAGS.scanATA) + { + scanControl |= ATA_DRIVES; + } + if (SCAN_FLAGS.scanUSB) + { + scanControl |= USB_DRIVES; + } + if (SCAN_FLAGS.scanSCSI) + { + scanControl |= SCSI_DRIVES; + } + if (SCAN_FLAGS.scanNVMe) + { + scanControl |= NVME_DRIVES; + } + if (SCAN_FLAGS.scanRAID) + { + scanControl |= RAID_DRIVES; + } + //set the interface types to show (if none are set, the lower level code assumes we need to show everything) + if (SCAN_FLAGS.scanInterfaceATA) + { + scanControl |= IDE_INTERFACE_DRIVES; + } + if (SCAN_FLAGS.scanInterfaceUSB) + { + scanControl |= USB_INTERFACE_DRIVES; + } + if (SCAN_FLAGS.scanInterfaceSCSI) + { + scanControl |= SCSI_INTERFACE_DRIVES; + } + if (SCAN_FLAGS.scanInterfaceNVMe) + { + scanControl |= NVME_INTERFACE_DRIVES; + } +#if defined (ENABLE_CSMI) + if (SCAN_FLAGS.scanIgnoreCSMI) + { + scanControl |= IGNORE_CSMI; + } + if (SCAN_FLAGS.scanAllowDuplicateDevices) + { + scanControl |= ALLOW_DUPLICATE_DEVICE; + } +#endif + if (ONLY_SEAGATE_FLAG) + { + scanControl |= SCAN_SEAGATE_ONLY; + } + scan_And_Print_Devs(scanControl, toolVerbosity); + } + // Add to this if list anything that is suppose to be independent. + // e.g. you can't say enumerate & then pull logs in the same command line. + // SIMPLE IS BEAUTIFUL + if (SCAN_FLAG || AGRESSIVE_SCAN_FLAG || SHOW_BANNER_FLAG || LICENSE_FLAG || SHOW_HELP_FLAG) + { + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_NO_ERROR); + } + + //print out errors for unknown arguments for remaining args that haven't been processed yet + for (argIndex = optind; argIndex < argc; argIndex++) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Invalid argument: %s\n", argv[argIndex]); + } + } + + if (!is_Running_Elevated()) + { + print_Elevated_Privileges_Text(); + } + + if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) + { + uint64_t flags = 0; + if (SUCCESS != get_Device_Count(&DEVICE_LIST_COUNT, flags)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to get number of devices\n"); + } + if (!is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + } + else if (DEVICE_LIST_COUNT == 0) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("You must specify one or more target devices with the --%s option to run this command.\n", DEVICE_LONG_OPT_STRING); + utility_Usage(true); + printf("Use -h option for detailed description\n\n"); + } + exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); + } + + if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) + || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) + || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) + || (FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) + || (FORCE_SCSI_FLAG && (FORCE_ATA_PIO_FLAG || FORCE_ATA_DMA_FLAG || FORCE_ATA_UDMA_FLAG))//We may need to remove this. At least when software SAT gets used. (currently only Windows ATA passthrough and FreeBSD ATA passthrough) + ) + { + printf("\nError: Only one force flag can be used at a time.\n"); + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + //need to make sure this is set when we are asked for SAT Info + if (SAT_INFO_FLAG) + { + DEVICE_INFO_FLAG = goTrue; + } + + if ((RAW_TFR_COMMAND || RAW_TFR_SIZE_FLAG > 0) && (RAW_CDB_LEN_FLAG > 0 && !is_Empty(RAW_CDB_ARRAY, UINT8_MAX))) + { + printf("\nError: CDB or TFR. Both were specified, but only one is allowed at a time by this utility.\n"); + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + + //check that we were given at least one test to perform...if not, show the help and exit + if (!(DEVICE_INFO_FLAG + || TEST_UNIT_READY_FLAG + //check for other tool specific options here + || (RAW_TFR_COMMAND || RAW_TFR_SIZE_FLAG > 0) + || (RAW_CDB_LEN_FLAG > 0 && !is_Empty(RAW_CDB_ARRAY, UINT8_MAX)) + )) + { + utility_Usage(true); + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + + uint64_t flags = 0; + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + if (!DEVICE_LIST) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to allocate memory\n"); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + exit(UTIL_EXIT_OPERATION_FAILURE); + } + versionBlock version; + memset(&version, 0, sizeof(versionBlock)); + version.version = DEVICE_BLOCK_VERSION; + version.size = sizeof(tDevice); + + if (!(DEVICE_INFO_FLAG || TEST_UNIT_READY_FLAG)) + { + flags = OPEN_HANDLE_ONLY; + } + + if (TEST_UNIT_READY_FLAG) + { + flags = DO_NOT_WAKE_DRIVE; + } + + if (FAST_DISCOVERY_FLAG) + { + flags = FAST_SCAN; + } + + if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) + { + + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) + { + DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; + } + ret = get_Device_List(DEVICE_LIST, DEVICE_LIST_COUNT * sizeof(tDevice), version, flags); + if (SUCCESS != ret) + { + if (ret == WARN_NOT_ALL_DEVICES_ENUMERATED) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("WARN: Not all devices enumerated correctly\n"); + } + } + else if (ret == PERMISSION_DENIED) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("WARN: Not all devices were opened. Some failed for lack of permissions\n"); + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unable to get device list\n"); + } + if (!is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + } + } + else + { + /*need to go through the handle list and attempt to open each handle.*/ + for (uint32_t handleIter = 0; handleIter < DEVICE_LIST_COUNT; ++handleIter) + { + /*Initializing is necessary*/ + deviceList[handleIter].sanity.size = sizeof(tDevice); + deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; +#if defined (UEFI_C_SOURCE) + deviceList[handleIter].os_info.fd = M_NULLPTR; +#elif !defined(_WIN32) + deviceList[handleIter].os_info.fd = -1; +#if defined(VMK_CROSS_COMP) + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; +#endif +#else + deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; +#endif + deviceList[handleIter].dFlags = flags; + + deviceList[handleIter].deviceVerbosity = toolVerbosity; + + if (ENABLE_LEGACY_PASSTHROUGH_FLAG) + { + deviceList[handleIter].drive_info.ata_Options.enableLegacyPassthroughDetectionThroughTrialAndError = true; + } + + /*get the device for the specified handle*/ +#if defined(_DEBUG) + printf("Attempting to open handle \"%s\"\n", HANDLE_LIST[handleIter]); +#endif + ret = get_Device(HANDLE_LIST[handleIter], &deviceList[handleIter]); +#if !defined(_WIN32) +#if !defined(VMK_CROSS_COMP) + if ((deviceList[handleIter].os_info.fd < 0) || +#else + if (((deviceList[handleIter].os_info.fd < 0) && + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || +#endif + (ret == FAILURE || ret == PERMISSION_DENIED)) +#else + if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) +#endif + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + } + } + free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); + for (uint32_t deviceIter = 0; deviceIter < DEVICE_LIST_COUNT; ++deviceIter) + { + deviceList[deviceIter].deviceVerbosity = toolVerbosity; + if (ONLY_SEAGATE_FLAG) + { + if (is_Seagate_Family(&deviceList[deviceIter]) == NON_SEAGATE) + { + /*if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive (%s) is not a Seagate drive.\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification); + }*/ + continue; + } + } + + //check for model number match + if (MODEL_MATCH_FLAG) + { + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive (%s) does not match the input model number: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG); + } + continue; + } + } + //check for fw match + if (FW_MATCH_FLAG) + { + if (strcmp(FW_STRING_FLAG, deviceList[deviceIter].drive_info.product_revision)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive's firmware (%s) does not match the input firmware revision: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_revision, FW_STRING_FLAG); + } + continue; + } + } + + //check for child model number match + if (CHILD_MODEL_MATCH_FLAG) + { + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive (%s) does not match the input child model number: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG); + } + continue; + } + } + //check for child fw match + if (CHILD_FW_MATCH_FLAG) + { + if (strcmp(CHILD_FW_STRING_FLAG, deviceList[deviceIter].drive_info.bridge_info.childDriveFW)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("%s - This drive's firmware (%s) does not match the input child firmware revision: %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.bridge_info.childDriveFW, CHILD_FW_STRING_FLAG); + } + continue; + } + } + if (FORCE_SCSI_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing SCSI Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = SCSI_DRIVE; + } + + if (FORCE_ATA_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing ATA Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; + } + + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\n%s - %s - %s - %s - %s\n", deviceList[deviceIter].os_info.name, deviceList[deviceIter].drive_info.product_identification, deviceList[deviceIter].drive_info.serialNumber, deviceList[deviceIter].drive_info.product_revision, print_drive_type(&deviceList[deviceIter])); + } + + //now start looking at what operations are going to be performed and kick them off + if (DEVICE_INFO_FLAG) + { + if (SUCCESS != print_Drive_Information(&deviceList[deviceIter], SAT_INFO_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: failed to get device information\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + } + } + + if (TEST_UNIT_READY_FLAG) + { + show_Test_Unit_Ready_Status(&deviceList[deviceIter]); + } + + //TODO: hard and soft reset flags that will issue the SAT command to the device? If that fails try OS APIs? + + //validate that we were given all the info we needed..starting with a CDB + if (RAW_CDB_LEN_FLAG > 0 || !is_Empty(RAW_CDB_ARRAY, UINT8_MAX)) + { + //now check that we were given a valid CDB length + if (RAW_CDB_LEN_FLAG > 0) + { + //check that a data direction was set + if (RAW_DATA_DIRECTION_FLAG != -1) + { + bool dataLenValidForTransferDir = true; + if (RAW_DATA_LEN_FLAG == 0 && RAW_DATA_DIRECTION_FLAG != XFER_NO_DATA) + { + dataLenValidForTransferDir = false; + } + if (dataLenValidForTransferDir) + { + bool showSenseData = true;//set to false upon successful completion only + uint8_t* dataBuffer = M_NULLPTR;//will be allocated shortly + uint32_t allocatedDataLength = 0; + const char* fileAccessMode = M_NULLPTR; + //now based on the data direction we need to allocate memory + switch (RAW_DATA_DIRECTION_FLAG) + { + case XFER_NO_DATA: + //nothing needs to be allocated...no data + break; + case XFER_DATA_IN: + //allocate memory. Also, check for an output file to open...if there isn't one, that's ok since we'll just print to the screen + if (!RAW_OUTPUT_FILE_NAME_FLAG) + { + //not a critical failure, just display a warning that the data won't be saved + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("WARNING: An output file was not specified, so the returned data will not be saved.\n"); + } + } + //no "else" needed + if (RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG) + { + //allocate based on logical block size + allocatedDataLength = deviceList[deviceIter].drive_info.deviceBlockSize * RAW_DATA_LEN_FLAG; + + } + else + { + //allocate based on the data size the user entered + allocatedDataLength = RAW_DATA_LEN_FLAG; + } + dataBuffer = C_CAST(uint8_t*, safe_calloc_aligned(allocatedDataLength, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + if (!dataBuffer) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to allocate memory for data in command!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + break; + case XFER_DATA_OUT: + //allocate memory. Also, check for an output file to open...if there isn't one, we need to return an error + if (!RAW_INPUT_FILE_NAME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: An input file is required for a data out command!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + else + { + int64_t fileOffset = RAW_INPUT_FILE_OFFSET_FLAG; + if (RAW_INPUT_OFFSET_ADJUST_BY_BLOCKS_FLAG) + { + fileOffset = deviceList[deviceIter].drive_info.deviceBlockSize * RAW_INPUT_FILE_OFFSET_FLAG; + } + if (RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG) + { + //allocate based on logical block size + allocatedDataLength = deviceList[deviceIter].drive_info.deviceBlockSize * RAW_DATA_LEN_FLAG; + } + else + { + //allocate based on the data size the user entered + allocatedDataLength = RAW_DATA_LEN_FLAG; + } + dataBuffer = C_CAST(uint8_t*, safe_calloc_aligned(allocatedDataLength, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + if (!dataBuffer) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to allocate memory for data in command!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + if (RAW_INPUT_FILE_NAME_FLAG) + { + fileAccessMode = "rb"; + RAW_INPUT_FILE_FLAG = secure_Open_File(RAW_INPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_INPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open file for reading data to send to drive!\n"); + } + safe_Free_aligned(C_CAST(void**, &dataBuffer)); + exit(UTIL_EXIT_OPERATION_FAILURE); + } + eUtilExitCodes inputfilexit = UTIL_EXIT_NO_ERROR; + do + { + if (SEC_FILE_SUCCESS != secure_Seek_File(RAW_INPUT_FILE_FLAG, fileOffset, 0)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to seek to specified offset in file!\n"); + } + inputfilexit = UTIL_EXIT_OPERATION_FAILURE; + break; + } + //now copy this data to the data buffer before we send the command + if (SEC_FILE_SUCCESS != secure_Read_File(RAW_INPUT_FILE_FLAG, dataBuffer, allocatedDataLength, sizeof(uint8_t), allocatedDataLength, M_NULLPTR)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to read file for datalen specified to send to drive!\n"); + } + inputfilexit = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + while (0); + + //close the file now that we are done reading it + if (SEC_FILE_SUCCESS != secure_Close_File(RAW_INPUT_FILE_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Unable to close handle to input file!\n"); + } + inputfilexit = UTIL_EXIT_OPERATION_FAILURE; + } + free_Secure_File_Info(&RAW_INPUT_FILE_FLAG); + if (inputfilexit != UTIL_EXIT_NO_ERROR) + { + safe_Free_aligned(C_CAST(void**, &dataBuffer)); + exit(C_CAST(int, inputfilexit)); + } + } + } + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Unknown Data Direction. Utility Failure!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + break; + } + //try issuing the command now + switch (scsi_Send_Cdb(&deviceList[deviceIter], RAW_CDB_ARRAY, C_CAST(eCDBLen, RAW_CDB_LEN_FLAG), dataBuffer, allocatedDataLength, C_CAST(eDataTransferDirection, RAW_DATA_DIRECTION_FLAG), deviceList[deviceIter].drive_info.lastCommandSenseData, SPC3_SENSE_LEN, RAW_TIMEOUT_FLAG)) + { + case IN_PROGRESS://separate case so we can save the sense data + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Command completed with an in progress status\n"); + } + //check for an output file to open and save the data to if, if it's a data in transfer + if (RAW_OUTPUT_FILE_NAME_FLAG) + { + fileAccessMode = "ab"; + RAW_OUTPUT_FILE_FLAG = secure_Open_File(RAW_OUTPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_OUTPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open/create file for saving returned data!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + break; + case SUCCESS: + showSenseData = false;//no need to show the sense data or save it... + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Command completed with good status\n"); + } + //check for an output file to open and save the data to if, if it's a data in transfer + if (RAW_OUTPUT_FILE_NAME_FLAG && RAW_DATA_DIRECTION_FLAG == XFER_DATA_IN) + { + fileAccessMode = "ab"; + RAW_OUTPUT_FILE_FLAG = secure_Open_File(RAW_OUTPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_OUTPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open/create file for saving returned data!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + break; + case NOT_SUPPORTED: + case OS_PASSTHROUGH_FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Operation not supported by low level driver or HBA.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case FAILURE: + case COMMAND_FAILURE: + case ABORTED: + case FROZEN: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Command completed with a failing status. See sense data.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + //check for an output file to open and save the data to if, if it's a data in transfer + if (RAW_OUTPUT_FILE_NAME_FLAG && RAW_DATA_DIRECTION_FLAG != XFER_DATA_IN) + { + fileAccessMode = "ab"; + RAW_OUTPUT_FILE_FLAG = secure_Open_File(RAW_OUTPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_OUTPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open/create file for saving returned sense data!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("An unknown internal error occured and cannot be recovered. Sense data not available.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + //if there is an outputfile, + if (RAW_OUTPUT_FILE_FLAG) + { + if (RAW_DATA_DIRECTION_FLAG == XFER_DATA_IN) + { + if (SEC_FILE_SUCCESS != secure_Write_File(RAW_OUTPUT_FILE_FLAG, dataBuffer, allocatedDataLength, sizeof(uint8_t), allocatedDataLength, M_NULLPTR)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error writing data to a file!\n"); + } + exitCode = UTIL_EXIT_ERROR_WRITING_FILE; + } + } + else + { + //save the sense data + if (SEC_FILE_SUCCESS != secure_Write_File(RAW_OUTPUT_FILE_FLAG, deviceList[deviceIter].drive_info.lastCommandSenseData, SPC3_SENSE_LEN, sizeof(uint8_t), SPC3_SENSE_LEN, M_NULLPTR)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error writing sense data to a file!\n"); + } + exitCode = UTIL_EXIT_ERROR_WRITING_FILE; + } + } + if (RAW_OUTPUT_FILE_FLAG && SEC_FILE_SUCCESS != secure_Flush_File(RAW_OUTPUT_FILE_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error flushing data!\n"); + } + exitCode = UTIL_EXIT_ERROR_WRITING_FILE; + } + if (RAW_OUTPUT_FILE_FLAG) + { + //close the file now that we are done reading it + if (SEC_FILE_SUCCESS != secure_Close_File(RAW_OUTPUT_FILE_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Unable to close handle to output file!\n"); + } + } + free_Secure_File_Info(&RAW_OUTPUT_FILE_FLAG); + } + } + + //show the returned data on data in commands when verbosity is less than 3 + if (RAW_DATA_DIRECTION_FLAG == XFER_DATA_IN && toolVerbosity < VERBOSITY_BUFFERS) + { + printf("\nReturned Data:\n"); + print_Data_Buffer(dataBuffer, allocatedDataLength, true); + } + + //show the sense data if the flag is set and verbosity is less than 3 + if (toolVerbosity < VERBOSITY_BUFFERS && showSenseData) + { + printf("\nSense Data:\n"); + print_Data_Buffer(deviceList[deviceIter].drive_info.lastCommandSenseData, SPC3_SENSE_LEN, true); + } + safe_Free_aligned(C_CAST(void**, &dataBuffer)); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Data Length is required for data in and data out commands!\n"); + } + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Data Direction was not given!\n"); + } + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: CDB Length not given!\n"); + } + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + } + } + + //perform some sort of validation to see that we have some command to send...then build it and send it. + if (RAW_TFR_SIZE_FLAG != 0 && RAW_TFR_PROTOCOL != -1 && RAW_TFR_XFER_LENGTH_LOCATION != -1 && RAW_TFR_BYTE_BLOCK != -1) + { + ataPassthroughCommand passthroughCommand; + memset(&passthroughCommand, 0, sizeof(ataPassthroughCommand)); + passthroughCommand.tfr.CommandStatus = RAW_TFR_COMMAND; + passthroughCommand.tfr.ErrorFeature = RAW_TFR_FEATURE; + passthroughCommand.tfr.Feature48 = RAW_TFR_FEATURE_EXT; + passthroughCommand.tfr.LbaLow = RAW_TFR_LBA_LOW; + passthroughCommand.tfr.LbaMid = RAW_TFR_LBA_MID; + passthroughCommand.tfr.LbaHi = RAW_TFR_LBA_HIGH; + passthroughCommand.tfr.LbaLow48 = RAW_TFR_LBA_LOW_EXT; + passthroughCommand.tfr.LbaMid48 = RAW_TFR_LBA_MID_EXT; + passthroughCommand.tfr.LbaHi48 = RAW_TFR_LBA_HIGH_EXT; + passthroughCommand.tfr.DeviceHead = RAW_TFR_DEVICE_HEAD; + passthroughCommand.tfr.SectorCount = RAW_TFR_SECTOR_COUNT; + passthroughCommand.tfr.SectorCount48 = RAW_TFR_SECTOR_COUNT_EXT; + passthroughCommand.tfr.icc = RAW_TFR_ICC; + passthroughCommand.tfr.aux1 = RAW_TFR_AUX1; + passthroughCommand.tfr.aux2 = RAW_TFR_AUX2; + passthroughCommand.tfr.aux3 = RAW_TFR_AUX3; + passthroughCommand.tfr.aux4 = RAW_TFR_AUX4; + + //set check condition + passthroughCommand.forceCheckConditionBit = RAW_TFR_CHECK_CONDITION; + + //set the protocol + passthroughCommand.commadProtocol = C_CAST(eAtaProtocol, RAW_TFR_PROTOCOL); + + //set xfer direction + passthroughCommand.commandDirection = C_CAST(eDataTransferDirection, RAW_DATA_DIRECTION_FLAG); + + //set where the length is in the command + passthroughCommand.ataCommandLengthLocation = C_CAST(eATAPassthroughLength, RAW_TFR_XFER_LENGTH_LOCATION); + + //check if we are doing a transfer based on logical blocks + switch (RAW_TFR_BYTE_BLOCK) + { + case 0: + passthroughCommand.ataTransferBlocks = ATA_PT_NO_DATA_TRANSFER; + break; + case 1: + passthroughCommand.ataTransferBlocks = ATA_PT_NUMBER_OF_BYTES; + break; + case UINT8_MAX: + passthroughCommand.ataTransferBlocks = ATA_PT_LOGICAL_SECTOR_SIZE; + break; + case 512: + default: + passthroughCommand.ataTransferBlocks = ATA_PT_512B_BLOCKS; + break; + } + + //set the command size + switch (RAW_TFR_SIZE_FLAG) + { + case 28: + passthroughCommand.commandType = ATA_CMD_TYPE_TASKFILE; + break; + case 48: + passthroughCommand.commandType = ATA_CMD_TYPE_EXTENDED_TASKFILE; + break; + case 0xFF: + passthroughCommand.commandType = ATA_CMD_TYPE_COMPLETE_TASKFILE; + break; + default: + passthroughCommand.commandType = ATA_CMD_TYPE_UNKNOWN; + break; + } + + if (passthroughCommand.commandType != ATA_CMD_TYPE_COMPLETE_TASKFILE && (passthroughCommand.tfr.icc || passthroughCommand.tfr.aux1 || passthroughCommand.tfr.aux2 || passthroughCommand.tfr.aux3 || passthroughCommand.tfr.aux4)) + { + //If ANY of these registers are set, we MUST use a complete taskfile + passthroughCommand.commandType = ATA_CMD_TYPE_COMPLETE_TASKFILE; + } + + //set the timeout + passthroughCommand.timeout = RAW_TIMEOUT_FLAG; + + //perform some validation based on the things we've filled in so far before we issue the command. + //check that a data direction was set + if (RAW_DATA_DIRECTION_FLAG != -1) + { + bool dataLenValidForTransferDir = true; + if (RAW_DATA_LEN_FLAG == 0 && RAW_DATA_DIRECTION_FLAG != XFER_NO_DATA) + { + dataLenValidForTransferDir = false; + } + if (dataLenValidForTransferDir) + { + bool showSenseData = true;//set to false upon successfil completion only + uint8_t* dataBuffer = M_NULLPTR;//will be allocated shortly + uint32_t allocatedDataLength = 0; + const char* fileAccessMode = M_NULLPTR; + //now based on the data direction we need to allocate memory + switch (RAW_DATA_DIRECTION_FLAG) + { + case XFER_NO_DATA: + //nothing needs to be allocated...no data + //TODO: check that all the non-data flags are set the same! + break; + case XFER_DATA_IN: + //allocate memory. Also, check for an output file to open...if there isn't one, that's ok since we'll just print to the screen + if (!RAW_OUTPUT_FILE_NAME_FLAG) + { + //not a critical failure, just display a warning that the data won't be saved + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("WARNING: An output file was not specified, so the returned data will not be saved.\n"); + } + } + //no "else" needed + if (RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG) + { + //allocate based on logical block size + allocatedDataLength = deviceList[deviceIter].drive_info.deviceBlockSize * RAW_DATA_LEN_FLAG; + + } + else + { + //allocate based on the data size the user entered + allocatedDataLength = RAW_DATA_LEN_FLAG; + } + dataBuffer = C_CAST(uint8_t*, safe_calloc_aligned(allocatedDataLength, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + if (!dataBuffer) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to allocate memory for data in command!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + break; + case XFER_DATA_OUT: + //allocate memory. Also, check for an output file to open...if there isn't one, we need to return an error + if (!RAW_INPUT_FILE_NAME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: An input file is required for a data out command!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + else + { + int64_t fileOffset = RAW_INPUT_FILE_OFFSET_FLAG; + if (RAW_INPUT_OFFSET_ADJUST_BY_BLOCKS_FLAG) + { + fileOffset = deviceList[deviceIter].drive_info.deviceBlockSize * RAW_INPUT_FILE_OFFSET_FLAG; + } + if (RAW_DATA_LEN_ADJUST_BY_BLOCKS_FLAG) + { + //allocate based on logical block size + allocatedDataLength = deviceList[deviceIter].drive_info.deviceBlockSize * RAW_DATA_LEN_FLAG; + } + else + { + //allocate based on the data size the user entered + allocatedDataLength = RAW_DATA_LEN_FLAG; + } + dataBuffer = C_CAST(uint8_t*, safe_calloc_aligned(allocatedDataLength, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + if (!dataBuffer) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to allocate memory for data in command!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + if (RAW_INPUT_FILE_NAME_FLAG) + { + fileAccessMode = "rb"; + RAW_INPUT_FILE_FLAG = secure_Open_File(RAW_INPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_INPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open file for reading data to send to drive!\n"); + } + safe_Free_aligned(C_CAST(void**, &dataBuffer)); + exit(UTIL_EXIT_OPERATION_FAILURE); + } + eUtilExitCodes inputfilexit = UTIL_EXIT_NO_ERROR; + do + { + if (SEC_FILE_SUCCESS != secure_Seek_File(RAW_INPUT_FILE_FLAG, fileOffset, 0)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to seek to specified offset in file!\n"); + } + inputfilexit = UTIL_EXIT_OPERATION_FAILURE; + break; + } + //now copy this data to the data buffer before we send the command + if (SEC_FILE_SUCCESS != secure_Read_File(RAW_INPUT_FILE_FLAG, dataBuffer, allocatedDataLength, sizeof(uint8_t), allocatedDataLength, M_NULLPTR)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to read file for datalen specified to send to drive!\n"); + } + inputfilexit = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } while (0); + + //close the file now that we are done reading it + if (SEC_FILE_SUCCESS != secure_Close_File(RAW_INPUT_FILE_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Unable to close handle to input file!\n"); + } + inputfilexit = UTIL_EXIT_OPERATION_FAILURE; + } + free_Secure_File_Info(&RAW_INPUT_FILE_FLAG); + if (inputfilexit != UTIL_EXIT_NO_ERROR) + { + safe_Free_aligned(C_CAST(void**, &dataBuffer)); + exit(C_CAST(int, inputfilexit)); + } + } + } + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Unknown Data Direction. Utility Failure!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + break; + } + passthroughCommand.ptrData = dataBuffer; + passthroughCommand.dataSize = allocatedDataLength; + //try issuing the command now + switch (ata_Passthrough_Command(&deviceList[deviceIter], &passthroughCommand)) + { + case IN_PROGRESS://separate case so we can save the sense data + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Command completed with an in progress status\n"); + } + //check for an output file to open and save the data to if, if it's a data in transfer + if (RAW_OUTPUT_FILE_NAME_FLAG) + { + fileAccessMode = "ab"; + RAW_OUTPUT_FILE_FLAG = secure_Open_File(RAW_OUTPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_OUTPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open/create file for saving returned data!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + break; + case SUCCESS: + showSenseData = false;//no need to show the sense data or save it... + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Command completed with good status\n"); + } + //check for an output file to open and save the data to if, if it's a data in transfer + if (RAW_OUTPUT_FILE_NAME_FLAG && RAW_DATA_DIRECTION_FLAG == XFER_DATA_IN) + { + fileAccessMode = "ab"; + RAW_OUTPUT_FILE_FLAG = secure_Open_File(RAW_OUTPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_OUTPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open/create file for saving returned data!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + break; + case NOT_SUPPORTED: + case OS_PASSTHROUGH_FAILURE: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Operation not supported by low level driver or HBA.\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + case FAILURE: + case COMMAND_FAILURE: + case ABORTED: + case FROZEN: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Command completed with a failing status. See sense data.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + //check for an output file to open and save the data to if, if it's a data in transfer + if (RAW_OUTPUT_FILE_NAME_FLAG && RAW_DATA_DIRECTION_FLAG != XFER_DATA_IN) + { + fileAccessMode = "ab"; + RAW_OUTPUT_FILE_FLAG = secure_Open_File(RAW_OUTPUT_FILE_NAME_FLAG, fileAccessMode, M_NULLPTR, M_NULLPTR, M_NULLPTR); + if (!RAW_OUTPUT_FILE_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Failed to open/create file for saving returned sense data!\n"); + } + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("An unknown internal error occured and cannot be recovered. Sense data not available.\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + //if there is an outputfile, + if (RAW_OUTPUT_FILE_FLAG) + { + if (RAW_DATA_DIRECTION_FLAG == XFER_DATA_IN) + { + if (SEC_FILE_SUCCESS != secure_Write_File(RAW_OUTPUT_FILE_FLAG, dataBuffer, allocatedDataLength, sizeof(uint8_t), allocatedDataLength, M_NULLPTR)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error writing data to a file!\n"); + } + exitCode = UTIL_EXIT_ERROR_WRITING_FILE; + } + } + else + { + //save the sense data + if (SEC_FILE_SUCCESS != secure_Write_File(RAW_OUTPUT_FILE_FLAG, deviceList[deviceIter].drive_info.lastCommandSenseData, SPC3_SENSE_LEN, sizeof(uint8_t), SPC3_SENSE_LEN, M_NULLPTR)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error writing sense data to a file!\n"); + } + exitCode = UTIL_EXIT_ERROR_WRITING_FILE; + } + } + if (RAW_OUTPUT_FILE_FLAG && SEC_FILE_SUCCESS != secure_Flush_File(RAW_OUTPUT_FILE_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Error flushing data!\n"); + } + exitCode = UTIL_EXIT_ERROR_WRITING_FILE; + } + if (RAW_OUTPUT_FILE_FLAG) + { + //close the file now that we are done reading it + if (SEC_FILE_SUCCESS != secure_Close_File(RAW_OUTPUT_FILE_FLAG)) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Unable to close handle to output file!\n"); + } + } + free_Secure_File_Info(&RAW_OUTPUT_FILE_FLAG); + } + } + + + //show the returned data on data in commands when verbosity is less than 3 + if (RAW_DATA_DIRECTION_FLAG == XFER_DATA_IN && toolVerbosity < VERBOSITY_BUFFERS) + { + printf("\nReturned Data:\n"); + print_Data_Buffer(dataBuffer, allocatedDataLength, true); + } + + //show the sense data if the flag is set and verbosity is less than 3 + if (toolVerbosity < VERBOSITY_BUFFERS && showSenseData) + { + printf("\nRTFRs:\n"); + printf("\t[Error] = %02" PRIX8 "h\n", passthroughCommand.rtfr.error); + if (passthroughCommand.commandType == ATA_CMD_TYPE_EXTENDED_TASKFILE || passthroughCommand.commandType == ATA_CMD_TYPE_COMPLETE_TASKFILE) + { + printf("\t[Count Ext] = %02" PRIX8 "h\n", passthroughCommand.rtfr.secCntExt); + } + printf("\t[Count] = %02" PRIX8 "h\n", passthroughCommand.rtfr.secCnt); + if (passthroughCommand.commandType == ATA_CMD_TYPE_EXTENDED_TASKFILE || passthroughCommand.commandType == ATA_CMD_TYPE_COMPLETE_TASKFILE) + { + printf("\t[LBA Lo Ext] = %02" PRIX8 "h\n", passthroughCommand.rtfr.lbaLowExt); + } + printf("\t[LBA Lo] = %02" PRIX8 "h\n", passthroughCommand.rtfr.lbaLow); + if (passthroughCommand.commandType == ATA_CMD_TYPE_EXTENDED_TASKFILE || passthroughCommand.commandType == ATA_CMD_TYPE_COMPLETE_TASKFILE) + { + printf("\t[LBA Mid Ext] = %02" PRIX8 "h\n", passthroughCommand.rtfr.lbaMidExt); + } + printf("\t[LBA Mid] = %02" PRIX8 "h\n", passthroughCommand.rtfr.lbaMid); + if (passthroughCommand.commandType == ATA_CMD_TYPE_EXTENDED_TASKFILE || passthroughCommand.commandType == ATA_CMD_TYPE_COMPLETE_TASKFILE) + { + printf("\t[LBA Hi Ext] = %02" PRIX8 "h\n", passthroughCommand.rtfr.lbaHiExt); + } + printf("\t[LBA Hi] = %02" PRIX8 "h\n", passthroughCommand.rtfr.lbaHi); + printf("\t[Device] = %02" PRIX8 "h\n", passthroughCommand.rtfr.device); + printf("\t[Status] = %02" PRIX8 "h\n", passthroughCommand.rtfr.status); + printf("\n"); + printf("\nSense Data:\n"); + print_Data_Buffer(deviceList[deviceIter].drive_info.lastCommandSenseData, SPC3_SENSE_LEN, true); + } + safe_Free_aligned(C_CAST(void**, &dataBuffer)); + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Data Length is required for data in and data out commands!\n"); + } + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + } + } + else + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("ERROR: Data Direction was not given!\n"); + } + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + } + } + else + { + //try to tell the user which flags they missed setting + if (RAW_TFR_SIZE_FLAG == 0) + { + printf("You must add the --%s [28 | 48 | complete] command line option\n", RAW_TFR_SIZE_LONG_OPT_STRING); + } + if (RAW_TFR_PROTOCOL == -1) + { + printf("You must add the --%s [pio | dma | udma | fpdma | ncq | nodata | diag | dmaque | reset] command line option\n", RAW_TFR_PROTOCOL_LONG_OPT_STRING); + } + if (RAW_TFR_XFER_LENGTH_LOCATION == -1) + { + printf("You must add the --%s [sectorCount | feature | tpsiu | nodata] command line option\n", RAW_TFR_XFER_LENGTH_LOCATION_LONG_OPT_STRING); + } + if (RAW_TFR_BYTE_BLOCK == -1) + { + printf("You must add the --%s [512 | logical | bytes | nodata] command line option\n", RAW_TFR_BYTE_BLOCK_LONG_OPT_STRING); + } + exitCode = UTIL_EXIT_ERROR_IN_COMMAND_LINE; + } + //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. + close_Device(&deviceList[deviceIter]); + } + free_device_list(&DEVICE_LIST); + exit(exitCode); +} + +//----------------------------------------------------------------------------- +// +// Utility_usage() +// +//! \brief Description: Dump the utility usage information +// +// Entry: +//! \param NONE +//! +// Exit: +//! \return VOID +// +//----------------------------------------------------------------------------- +void utility_Usage(bool shortUsage) +{ + //everything needs a help option right? + printf("Usage\n"); + printf("=====\n"); + printf("\t %s [-d %s] {arguments} {options}\n\n", util_name, deviceHandleName); + + printf("\nExamples\n"); + printf("========\n"); + //example usage + printf("\t%s --%s\n", util_name, SCAN_LONG_OPT_STRING); + printf("\t%s -d %s -%c\n", util_name, deviceHandleExample, DEVICE_INFO_SHORT_OPT); + printf("\tIdentify device:\n"); + printf("\t\t-d %s --dataDir in --dataLen 512 --outputFile ID_dev.bin --tfrByteBlock 512 --tfrProtocol pio --tfrSize 28 --command ECh --tfrXferLengthReg sectorCount --sectorCount 1\n", deviceHandleExample); + //return codes + printf("\nReturn codes\n"); + printf("============\n"); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); + + //utility options - alphabetized + printf("\nUtility Options\n"); + printf("===============\n"); +#if defined (ENABLE_CSMI) + print_CSMI_Force_Flags_Help(shortUsage); + print_CSMI_Verbose_Help(shortUsage); +#endif + print_Echo_Command_Line_Help(shortUsage); + print_Enable_Legacy_USB_Passthrough_Help(shortUsage); + print_Force_ATA_Help(shortUsage); + print_Force_ATA_DMA_Help(shortUsage); + print_Force_ATA_PIO_Help(shortUsage); + print_Force_ATA_UDMA_Help(shortUsage); + print_Force_SCSI_Help(shortUsage); + print_Help_Help(shortUsage); + print_License_Help(shortUsage); + print_Model_Match_Help(shortUsage); + print_No_Banner_Help(shortUsage); + print_Firmware_Revision_Match_Help(shortUsage); + print_Only_Seagate_Help(shortUsage); + print_Quiet_Help(shortUsage, util_name); + print_Verbose_Help(shortUsage); + print_Version_Help(shortUsage, util_name); + + //the test options + printf("\nUtility Arguments\n"); + printf("=================\n"); + //Common (across utilities) - alphabetized + print_Device_Help(shortUsage, deviceHandleExample); + print_Scan_Flags_Help(shortUsage); + print_Device_Information_Help(shortUsage); + print_Scan_Help(shortUsage, deviceHandleExample); + print_Agressive_Scan_Help(shortUsage); + print_SAT_Info_Help(shortUsage); + print_Test_Unit_Ready_Help(shortUsage); + //utility tests/operations go here - alphabetized + //multiple interfaces + print_Fast_Discovery_Help(shortUsage); + print_Raw_Data_Direction_Help(shortUsage); + print_Raw_Data_Length_Help(shortUsage); + print_Raw_Input_File_Help(shortUsage); + print_Raw_Input_File_Offset_Help(shortUsage); + print_Raw_Output_File_Help(shortUsage); + print_Raw_Timeout_Help(shortUsage); + + //SATA Only Options + printf("\n\tSATA Only:\n\t=========\n"); + print_Raw_TFR_AUX1_Help(shortUsage); + print_Raw_TFR_AUX2_Help(shortUsage); + print_Raw_TFR_AUX3_Help(shortUsage); + print_Raw_TFR_AUX4_Help(shortUsage); + print_Raw_TFR_Aux_Full_Help(shortUsage); + print_Raw_TFR_Command_Help(shortUsage); + print_Raw_TFR_Device_Head_Help(shortUsage); + print_Raw_TFR_Feature_Help(shortUsage); + print_Raw_TFR_Feature_Ext_Help(shortUsage); + print_Raw_TFR_Feature_Full_Help(shortUsage); + print_Raw_TFR_ICC_Help(shortUsage); + print_Raw_TFR_LBA_Full_Help(shortUsage); + print_Raw_TFR_LBA_High_Help(shortUsage); + print_Raw_TFR_LBA_High_Ext_Help(shortUsage); + print_Raw_TFR_LBA_Low_Help(shortUsage); + print_Raw_TFR_LBA_Low_Ext_Help(shortUsage); + print_Raw_TFR_LBA_Mode_Help(shortUsage); + print_Raw_TFR_LBA_Mid_Help(shortUsage); + print_Raw_TFR_LBA_Mid_Ext_Help(shortUsage); + print_Raw_TFR_Sector_Count_Help(shortUsage); + print_Raw_TFR_Sector_Count_Ext_Help(shortUsage); + print_Raw_TFR_Sector_Count_Full_Help(shortUsage); + print_Raw_TFR_Byte_Block_Help(shortUsage); + print_Raw_TFR_Protocol_Help(shortUsage); + print_Raw_TFR_Check_Condition_Help(shortUsage); + print_Raw_TFR_Size_Help(shortUsage); + print_Raw_TFR_XFer_Length_Register_Help(shortUsage); + + //SAS/SCSI Only + printf("\n\tSAS Only:\n\t=========\n"); + print_Raw_CDB_Help(shortUsage); + print_Raw_CDB_Length_Help(shortUsage); +} diff --git a/utils/C/openSeaChest/openSeaChest_Reservations.c b/utils/C/openSeaChest/openSeaChest_Reservations.c index 353935e5..ec234f3b 100644 --- a/utils/C/openSeaChest/openSeaChest_Reservations.c +++ b/utils/C/openSeaChest/openSeaChest_Reservations.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,13 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -29,7 +32,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Reservations"; -const char *buildVersion = "0.2.1"; +const char *buildVersion = "0.3.0"; //////////////////////////// // functions to declare // @@ -49,14 +52,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -104,7 +107,7 @@ int32_t main(int argc, char *argv[]) LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -193,7 +196,7 @@ int32_t main(int argc, char *argv[]) //parse long options that have no short option and required arguments here if (strcmp(longopts[optionIndex].name, PERSISTENT_RESERVATION_KEY_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(optarg, &PERSISTENT_RESERVATION_KEY)) + if (get_And_Validate_Integer_Input_Uint64(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &PERSISTENT_RESERVATION_KEY)) { PERSISTENT_RESREVATION_KEY_VALID = true; } @@ -243,7 +246,7 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(longopts[optionIndex].name, PERSISTENT_RESERVATION_PREEMPT_LONG_OPT_STRING) == 0) { - if (get_And_Validate_Integer_Input(optarg, &PERSISTENT_RESERVATION_PREEMPT_KEY)) + if (get_And_Validate_Integer_Input_Uint64(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &PERSISTENT_RESERVATION_PREEMPT_KEY)) { PERSISTENT_RESERVATION_PREEMPT = true; } @@ -337,9 +340,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -376,7 +380,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -473,7 +477,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -529,6 +533,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -568,7 +574,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -611,7 +617,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -659,11 +665,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -687,7 +693,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -729,7 +735,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -754,7 +760,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -793,6 +799,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -901,12 +916,12 @@ int32_t main(int argc, char *argv[]) { uint16_t fullReservationsCount = 0; size_t fullReservationsDataSize = 0; - ptrFullReservationInfo fullInfo = NULL; + ptrFullReservationInfo fullInfo = M_NULLPTR; switch (get_Full_Status_Key_Count(&deviceList[deviceIter], &fullReservationsCount)) { case SUCCESS: fullReservationsDataSize = sizeof(fullReservationInfo) + (sizeof(fullReservationKeyInfo) * fullReservationsCount); - fullInfo = C_CAST(ptrFullReservationInfo, calloc(fullReservationsDataSize, sizeof(uint8_t))); + fullInfo = C_CAST(ptrFullReservationInfo, safe_calloc(fullReservationsDataSize, sizeof(uint8_t))); if (fullInfo) { fullInfo->size = fullReservationsDataSize; @@ -931,7 +946,7 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; break; } - safe_Free(fullInfo); + safe_free_full_reservation_info(&fullInfo); } else { @@ -974,13 +989,13 @@ int32_t main(int argc, char *argv[]) { uint16_t registrationKeyCount = 0; size_t registrationKeysDataSize = 0; - ptrRegistrationKeysData registrationKeys = NULL; + ptrRegistrationKeysData registrationKeys = M_NULLPTR; switch (get_Registration_Key_Count(&deviceList[deviceIter], ®istrationKeyCount)) { case SUCCESS: //allocate memory to read them registrationKeysDataSize = sizeof(registrationKeysData) + (sizeof(uint64_t) * registrationKeyCount); - registrationKeys = C_CAST(ptrRegistrationKeysData, calloc(registrationKeysDataSize, sizeof(uint8_t))); + registrationKeys = C_CAST(ptrRegistrationKeysData, safe_calloc(registrationKeysDataSize, sizeof(uint8_t))); if (registrationKeys) { registrationKeys->size = registrationKeysDataSize; @@ -1005,7 +1020,7 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; break; } - safe_Free(registrationKeys); + safe_free_registration_key_data(®istrationKeys); } else { @@ -1041,20 +1056,20 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; } } - + if (SHOW_RESERVATIONS) { if (prSupported) { uint16_t reservationKeyCount = 0; size_t reservationsDataSize = 0; - ptrReservationsData reservations = NULL; + ptrReservationsData reservations = M_NULLPTR; switch (get_Reservation_Count(&deviceList[deviceIter], &reservationKeyCount)) { case SUCCESS: //allocate memory to read them reservationsDataSize = sizeof(reservationsData) + (sizeof(reservationInfo) * reservationKeyCount); - reservations = C_CAST(ptrReservationsData, calloc(reservationsDataSize, sizeof(uint8_t))); + reservations = C_CAST(ptrReservationsData, safe_calloc(reservationsDataSize, sizeof(uint8_t))); if (reservations) { reservations->size = reservationsDataSize; @@ -1079,7 +1094,7 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_FAILURE; break; } - safe_Free(reservations); + safe_free_reservation_data(&reservations); } else { @@ -1128,7 +1143,7 @@ int32_t main(int argc, char *argv[]) } //persistent reservation type must be provided for these options. - if(!PERSISTENT_RESREVATION_TYPE_VALID && (PERSISTENT_RESERVATION_RESERVE || PERSISTENT_RESERVATION_RELEASE || PERSISTENT_RESERVATION_PREEMPT)) + if (!PERSISTENT_RESREVATION_TYPE_VALID && (PERSISTENT_RESERVATION_RESERVE || PERSISTENT_RESERVATION_RELEASE || PERSISTENT_RESERVATION_PREEMPT)) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1205,12 +1220,12 @@ int32_t main(int argc, char *argv[]) exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; } } - + if (PERSISTENT_RESERVATION_RESERVE) { if (prSupported) { - switch (acquire_Reservation(&deviceList[deviceIter], PERSISTENT_RESERVATION_KEY, PERSISTENT_RESERVATION_TYPE)) + switch (acquire_Reservation(&deviceList[deviceIter], PERSISTENT_RESERVATION_KEY, C_CAST(eReservationType, PERSISTENT_RESERVATION_TYPE))) { case SUCCESS: break; @@ -1244,7 +1259,7 @@ int32_t main(int argc, char *argv[]) { if (prSupported) { - switch (release_Reservation(&deviceList[deviceIter], PERSISTENT_RESERVATION_KEY, PERSISTENT_RESERVATION_TYPE)) + switch (release_Reservation(&deviceList[deviceIter], PERSISTENT_RESERVATION_KEY, C_CAST(eReservationType, PERSISTENT_RESERVATION_TYPE))) { case SUCCESS: break; @@ -1313,7 +1328,7 @@ int32_t main(int argc, char *argv[]) { if (prSupported) { - switch (preempt_Reservation(&deviceList[deviceIter], PERSISTENT_RESERVATION_KEY, PERSISTENT_RESERVATION_PREEMPT_KEY, M_ToBool(PERSISTENT_RESERVATION_PREEMPT_ABORT), PERSISTENT_RESERVATION_TYPE)) + switch (preempt_Reservation(&deviceList[deviceIter], PERSISTENT_RESERVATION_KEY, PERSISTENT_RESERVATION_PREEMPT_KEY, M_ToBool(PERSISTENT_RESERVATION_PREEMPT_ABORT), C_CAST(eReservationType, PERSISTENT_RESERVATION_TYPE))) { case SUCCESS: break; @@ -1349,7 +1364,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1387,11 +1402,11 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, SHOW_REGISTRATION_KEYS_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, SHOW_RESERVATIONS_LONG_OPT_STRING); //TODO: examples of creating a reservation, clearing, aborting, preempting, releasing - + //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); diff --git a/utils/C/openSeaChest/openSeaChest_SMART.c b/utils/C/openSeaChest/openSeaChest_SMART.c index 3ca0c81b..dbcc8fa0 100644 --- a/utils/C/openSeaChest/openSeaChest_SMART.c +++ b/utils/C/openSeaChest/openSeaChest_SMART.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,15 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif + +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "time_utils.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -33,7 +38,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_SMART"; -const char *buildVersion = "2.3.2"; +const char *buildVersion = "2.5.1"; //////////////////////////// // functions to declare // @@ -53,14 +58,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -116,6 +121,7 @@ int32_t main(int argc, char *argv[]) DEVICE_STATISTICS_VAR NVME_HEALTH_VAR LOWLEVEL_INFO_VAR + SMART_OFFLINE_SCAN_VAR int args = 0; int argIndex = 0; @@ -178,6 +184,7 @@ int32_t main(int argc, char *argv[]) #endif DEVICE_STATISTICS_LONG_OPT, NVME_HEALTH_LONG_OPT, + SMART_OFFLINE_SCAN_LONG_OPT, LONG_OPT_TERMINATOR }; @@ -214,13 +221,13 @@ int32_t main(int argc, char *argv[]) { case 0: //parse long options that have no short option and required arguments here - if (strncmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CONFIRM_LONG_OPT_STRING))) == 0) + if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { - if (strlen(optarg) == strlen(LONG_TEST_ACCEPT_STRING) && strncmp(optarg, LONG_TEST_ACCEPT_STRING, strlen(LONG_TEST_ACCEPT_STRING)) == 0) + if (strcmp(optarg, LONG_TEST_ACCEPT_STRING) == 0) { LONG_TEST_FLAG = true; } - else if (strlen(optarg) == strlen(SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING, strlen(SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING)) == 0) + else if (strcmp(optarg, SINGLE_SECTOR_DATA_ERASE_ACCEPT_STRING) == 0) { SINGLE_SECTOR_DATA_ERASE_FLAG = true; } @@ -230,7 +237,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, IDD_TEST_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(IDD_TEST_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, IDD_TEST_LONG_OPT_STRING) == 0) { RUN_IDD_FLAG = true; if (strcmp(optarg, "short") == 0) @@ -245,8 +252,7 @@ int32_t main(int argc, char *argv[]) { //read in the argument as a hex value instead of an integer uint32_t iddTestNumber = 0; - int res = sscanf(optarg, "%"SCNx32, &iddTestNumber); - if (res != EOF && res > 0) + if (get_And_Validate_Integer_Input_Uint32(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &iddTestNumber)) { switch (iddTestNumber) { @@ -269,15 +275,35 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, ERROR_LIMIT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ERROR_LIMIT_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ERROR_LIMIT_LONG_OPT_STRING) == 0) { - ERROR_LIMIT_FLAG = C_CAST(uint16_t, atoi(optarg)); - if(strstr(optarg, "l")) + char *unit = M_NULLPTR; + if (get_And_Validate_Integer_Input_Uint16(optarg, &unit, ALLOW_UNIT_SECTOR_TYPE, &ERROR_LIMIT_FLAG)) { - ERROR_LIMIT_LOGICAL_COUNT = true; + if (unit) + { + if (strcmp(unit, "l") == 0) + { + ERROR_LIMIT_LOGICAL_COUNT = true; + } + else if (strcmp(unit, "p") == 0) + { + ERROR_LIMIT_LOGICAL_COUNT = false; + } + else + { + print_Error_In_Cmd_Line_Args(ERROR_LIMIT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } + } + } + else + { + print_Error_In_Cmd_Line_Args(ERROR_LIMIT_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SMART_ATTRIBUTES_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_ATTRIBUTES_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SMART_ATTRIBUTES_LONG_OPT_STRING) == 0) { SMART_ATTRIBUTES_FLAG = true; if (strcmp(optarg, "raw") == 0) @@ -298,14 +324,14 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SMART_FEATURE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_FEATURE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SMART_FEATURE_LONG_OPT_STRING) == 0) { SMART_FEATURE_FLAG = true; - if(strcmp(optarg, "enable") == 0) + if (strcmp(optarg, "enable") == 0) { SMART_FEATURE_STATE_FLAG = true; } - else if(strcmp(optarg, "disable") == 0) + else if (strcmp(optarg, "disable") == 0) { SMART_FEATURE_STATE_FLAG = false; } @@ -315,26 +341,30 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SET_MRIE_MODE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SET_MRIE_MODE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SET_MRIE_MODE_LONG_OPT_STRING) == 0) { SET_MRIE_MODE_FLAG = true; - if(strcmp(optarg, "default") == 0) + if (strcmp(optarg, "default") == 0) { SET_MRIE_MODE_DEFAULT = true; } else { - SET_MRIE_MODE_VALUE = C_CAST(uint8_t, atoi(optarg)); + if (!get_And_Validate_Integer_Input_Uint8(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SET_MRIE_MODE_VALUE)) + { + print_Error_In_Cmd_Line_Args(SET_MRIE_MODE_LONG_OPT_STRING, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); + } } } - else if (strncmp(longopts[optionIndex].name, SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SMART_ATTR_AUTOSAVE_FEATURE_LONG_OPT_STRING) == 0) { SMART_ATTR_AUTOSAVE_FEATURE_FLAG = true; - if(strcmp(optarg, "enable") == 0) + if (strcmp(optarg, "enable") == 0) { SMART_ATTR_AUTOSAVE_FEATURE_STATE_FLAG = true; } - else if(strcmp(optarg, "disable") == 0) + else if (strcmp(optarg, "disable") == 0) { SMART_ATTR_AUTOSAVE_FEATURE_STATE_FLAG = false; } @@ -344,7 +374,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SMART_AUTO_OFFLINE_FEATURE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_AUTO_OFFLINE_FEATURE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SMART_AUTO_OFFLINE_FEATURE_LONG_OPT_STRING) == 0) { SMART_AUTO_OFFLINE_FEATURE_FLAG = true; if (strcmp(optarg, "enable") == 0) @@ -361,11 +391,11 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SCSI_DEFECTS_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SCSI_DEFECTS_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SCSI_DEFECTS_LONG_OPT_STRING) == 0) { size_t counter = 0; SCSI_DEFECTS_FLAG = true; - while (counter < strlen(optarg)) + while (counter < safe_strlen(optarg)) { if (optarg[counter] == 'p' || optarg[counter] == 'P') { @@ -384,14 +414,9 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING) == 0) { - //check for integer value or string that specifies the correct mode. - if (strlen(optarg) == 1 && isdigit(optarg[0])) - { - SCSI_DEFECTS_DESCRIPTOR_MODE = atoi(optarg); - } - else + if (!get_And_Validate_Integer_Input_I(optarg, M_NULLPTR, ALLOW_UNIT_NONE, &SCSI_DEFECTS_DESCRIPTOR_MODE)) { if (strcmp("shortBlock", optarg) == 0) { @@ -424,7 +449,7 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, SHOW_SMART_ERROR_LOG_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SHOW_SMART_ERROR_LOG_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SHOW_SMART_ERROR_LOG_LONG_OPT_STRING) == 0) { SHOW_SMART_ERROR_LOG_FLAG = true; if (strcmp("summary", optarg) == 0) @@ -442,7 +467,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING) == 0) { if (strcmp("raw", optarg) == 0 || strcmp("generic", optarg) == 0) { @@ -458,22 +483,22 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -485,14 +510,14 @@ int32_t main(int argc, char *argv[]) { case 0: //check long options for missing arguments - if (strncmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CONFIRM_LONG_OPT_STRING))) == 0) + if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { if (VERBOSITY_QUIET < toolVerbosity) { printf("You must add a confirmation string to the confirm option\n"); } } - else if (strncmp(longopts[optionIndex].name, IDD_TEST_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(IDD_TEST_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, IDD_TEST_LONG_OPT_STRING) == 0) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -538,7 +563,7 @@ int32_t main(int argc, char *argv[]) } break; case PROGRESS_SHORT_OPT://progress [test] - PROGRESS_CHAR = strdup(optarg); + PROGRESS_CHAR = optarg; break; case DEVICE_SHORT_OPT: //device if (0 != parse_Device_Handle_Argument(optarg, &RUN_ON_ALL_DRIVES, &USER_PROVIDED_HANDLE, &DEVICE_LIST_COUNT, &HANDLE_LIST)) @@ -565,9 +590,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -604,7 +630,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -701,7 +727,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -757,6 +783,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -783,7 +811,7 @@ int32_t main(int argc, char *argv[]) || LONG_DST_FLAG || ABORT_DST_FLAG || ABORT_IDD_FLAG - || (PROGRESS_CHAR != NULL) + || (PROGRESS_CHAR != M_NULLPTR) || RUN_IDD_FLAG || DST_AND_CLEAN_FLAG || SMART_FEATURE_FLAG @@ -797,6 +825,7 @@ int32_t main(int argc, char *argv[]) || SHOW_SMART_ERROR_LOG_FLAG || DEVICE_STATISTICS_FLAG || NVME_HEALTH_FLAG + || SMART_OFFLINE_SCAN_FLAG //check for other tool specific options here )) { @@ -806,7 +835,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -849,7 +878,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -897,11 +926,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -925,9 +954,9 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif - (ret == FAILURE || ret == PERMISSION_DENIED)) + (ret == FAILURE || ret == PERMISSION_DENIED)) #else if ((deviceList[handleIter].os_info.fd == INVALID_HANDLE_VALUE) || (ret == FAILURE || ret == PERMISSION_DENIED)) #endif @@ -937,7 +966,7 @@ int32_t main(int argc, char *argv[]) printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); - if(ret == PERMISSION_DENIED || !is_Running_Elevated()) + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) { exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); } @@ -967,7 +996,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -992,7 +1021,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1032,6 +1061,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1113,8 +1151,8 @@ int32_t main(int argc, char *argv[]) if (SCSI_DEFECTS_FLAG) { - ptrSCSIDefectList defects = NULL; - switch (get_SCSI_Defect_List(&deviceList[deviceIter], SCSI_DEFECTS_DESCRIPTOR_MODE, SCSI_DEFECTS_GROWN_LIST, SCSI_DEFECTS_PRIMARY_LIST, &defects)) + ptrSCSIDefectList defects = M_NULLPTR; + switch (get_SCSI_Defect_List(&deviceList[deviceIter], C_CAST(eSCSIAddressDescriptors, SCSI_DEFECTS_DESCRIPTOR_MODE), SCSI_DEFECTS_GROWN_LIST, SCSI_DEFECTS_PRIMARY_LIST, &defects)) { case SUCCESS: print_SCSI_Defect_List(defects); @@ -1154,6 +1192,7 @@ int32_t main(int argc, char *argv[]) { printf("\t%s\n", tripInfo.reasonString); } + print_SMART_Tripped_Message(is_SSD(&deviceList[deviceIter])); } exitCode = UTIL_EXIT_OPERATION_FAILURE; } @@ -1187,7 +1226,7 @@ int32_t main(int argc, char *argv[]) if (SMART_ATTRIBUTES_FLAG) { - switch (print_SMART_Attributes(&deviceList[deviceIter], SMART_ATTRIBUTES_MODE_FLAG)) + switch (print_SMART_Attributes(&deviceList[deviceIter], C_CAST(eSMARTAttrOutMode, SMART_ATTRIBUTES_MODE_FLAG))) { case SUCCESS: //nothing to print here since if it was successful, the attributes will be printed to the screen @@ -1288,7 +1327,7 @@ int32_t main(int argc, char *argv[]) break; } } - break; + break; default://error if (VERBOSITY_QUIET < toolVerbosity) { @@ -1301,7 +1340,7 @@ int32_t main(int argc, char *argv[]) if (ABORT_DST_FLAG) { - int abortResult = UNKNOWN; + eReturnValues abortResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Aborting DST\n"); @@ -1342,7 +1381,7 @@ int32_t main(int argc, char *argv[]) if (ABORT_IDD_FLAG) { - int abortResult = UNKNOWN; + eReturnValues abortResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Aborting IDD\n"); @@ -1381,9 +1420,49 @@ int32_t main(int argc, char *argv[]) } } + if (SMART_OFFLINE_SCAN_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("SMART Offline Data Collection\n"); + } + switch (run_SMART_Offline(&deviceList[deviceIter])) + { + case UNKNOWN: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("Unknown Error occurred while trying to start SMART Offline Scan\n"); + } + break; + case SUCCESS: + break; + case ABORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("SMART offline data collection was aborted by the host or some other operation on the drive.\n"); + } + exitCode = UTIL_EXIT_OPERATION_ABORTED; + break; + case NOT_SUPPORTED: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("SMART offline data collection is not supported on this device\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + break; + default: + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("SMART offline data collection Failed!\n"); + } + exitCode = UTIL_EXIT_OPERATION_FAILURE; + break; + } + } + if (SHORT_DST_FLAG) { - int32_t DSTResult = UNKNOWN; + eReturnValues DSTResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Short DST\n"); @@ -1445,7 +1524,7 @@ int32_t main(int argc, char *argv[]) if (CONVEYANCE_DST_FLAG) { - int32_t DSTResult = UNKNOWN; + eReturnValues DSTResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Conveyance DST\n"); @@ -1507,7 +1586,7 @@ int32_t main(int argc, char *argv[]) if (LONG_DST_FLAG) { - int32_t DSTResult = UNKNOWN; + eReturnValues DSTResult = UNKNOWN; if (VERBOSITY_QUIET < toolVerbosity) { printf("Long DST\n"); @@ -1518,7 +1597,7 @@ int32_t main(int argc, char *argv[]) printf("Drive reported long DST time as "); if (hours > 0) { - printf("%"PRIu8" hour", hours); + printf("%" PRIu8 " hour", hours); if (hours > 1) { printf("s "); @@ -1528,7 +1607,7 @@ int32_t main(int argc, char *argv[]) printf(" "); } } - printf("%"PRIu8" minute", minutes); + printf("%" PRIu8 " minute", minutes); if (minutes > 1) { printf("s"); @@ -1610,14 +1689,17 @@ int32_t main(int argc, char *argv[]) if (RUN_IDD_FLAG) { - int32_t IDDResult = UNKNOWN; - if (is_Seagate_Family(&deviceList[deviceIter]) == SEAGATE) + eReturnValues IDDResult = UNKNOWN; + eSeagateFamily family = is_Seagate_Family(&deviceList[deviceIter]); + if (family == SEAGATE) { if (VERBOSITY_QUIET < toolVerbosity) { uint64_t iddTimeSeconds = 0; - uint8_t hours = 0, minutes = 0, seconds = 0; - get_Approximate_IDD_Time(&deviceList[deviceIter], IDD_TEST_FLAG, &iddTimeSeconds); + uint8_t hours = 0; + uint8_t minutes = 0; + uint8_t seconds = 0; + get_Approximate_IDD_Time(&deviceList[deviceIter], C_CAST(eIDDTests, IDD_TEST_FLAG), &iddTimeSeconds); if (iddTimeSeconds == UINT64_MAX) { printf("A time estimate is not available for this IDD operation"); @@ -1625,12 +1707,12 @@ int32_t main(int argc, char *argv[]) else { printf("The In Drive Diagnostics (IDD) test will take approximately "); - convert_Seconds_To_Displayable_Time(iddTimeSeconds, NULL, NULL, &hours, &minutes, &seconds); - print_Time_To_Screen(NULL, NULL, &hours, &minutes, &seconds); + convert_Seconds_To_Displayable_Time(iddTimeSeconds, M_NULLPTR, M_NULLPTR, &hours, &minutes, &seconds); + print_Time_To_Screen(M_NULLPTR, M_NULLPTR, &hours, &minutes, &seconds); } printf("\n"); } - IDDResult = run_IDD(&deviceList[deviceIter], IDD_TEST_FLAG, POLL_FLAG, CAPTIVE_FOREGROUND_FLAG); + IDDResult = run_IDD(&deviceList[deviceIter], C_CAST(eIDDTests, IDD_TEST_FLAG), POLL_FLAG, CAPTIVE_FOREGROUND_FLAG); switch (IDDResult) { case UNKNOWN: @@ -1642,7 +1724,7 @@ int32_t main(int argc, char *argv[]) if (POLL_FLAG || IDD_TEST_FLAG == SEAGATE_IDD_SHORT || CAPTIVE_FOREGROUND_FLAG)//short test is run in captive mode, so polling doesn't make sense { printf("IDD - "); - switch(IDD_TEST_FLAG) + switch (IDD_TEST_FLAG) { case SEAGATE_IDD_SHORT: printf("short"); @@ -1659,7 +1741,7 @@ int32_t main(int argc, char *argv[]) else { printf("IDD - "); - switch(IDD_TEST_FLAG) + switch (IDD_TEST_FLAG) { case SEAGATE_IDD_SHORT: printf("short"); @@ -1718,6 +1800,14 @@ int32_t main(int argc, char *argv[]) break; } } + else if (family != NON_SEAGATE) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("IDD not supported on this device\n"); + } + exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; + } else { if (VERBOSITY_QUIET < toolVerbosity) @@ -1736,11 +1826,11 @@ int32_t main(int argc, char *argv[]) { printf("DST And Clean\n"); } - if(ERROR_LIMIT_LOGICAL_COUNT) + if (ERROR_LIMIT_LOGICAL_COUNT) { ERROR_LIMIT_FLAG *= C_CAST(uint16_t, deviceList[deviceIter].drive_info.devicePhyBlockSize / deviceList[deviceIter].drive_info.deviceBlockSize); } - switch (run_DST_And_Clean(&deviceList[deviceIter], ERROR_LIMIT_FLAG, NULL, NULL, NULL, NULL)) + switch (run_DST_And_Clean(&deviceList[deviceIter], ERROR_LIMIT_FLAG, M_NULLPTR, M_NULLPTR, M_NULLPTR, M_NULLPTR)) { case UNKNOWN: if (VERBOSITY_QUIET < toolVerbosity) @@ -1821,7 +1911,7 @@ int32_t main(int argc, char *argv[]) } } - if(SMART_FEATURE_FLAG) + if (SMART_FEATURE_FLAG) { switch (enable_Disable_SMART_Feature(&deviceList[deviceIter], SMART_FEATURE_STATE_FLAG)) { @@ -1829,7 +1919,7 @@ int32_t main(int argc, char *argv[]) if (VERBOSITY_QUIET < toolVerbosity) { printf("Successfully "); - if(SMART_FEATURE_STATE_FLAG) + if (SMART_FEATURE_STATE_FLAG) { printf("Enabled"); } @@ -1864,7 +1954,7 @@ int32_t main(int argc, char *argv[]) case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) { - printf("Successfully set MRIE mode to %" PRIu8"\n", SET_MRIE_MODE_VALUE); + printf("Successfully set MRIE mode to %" PRIu8 "\n", SET_MRIE_MODE_VALUE); if (deviceList[deviceIter].drive_info.numberOfLUs > 1) { printf("NOTE: This command may have affected more than 1 logical unit\n"); @@ -1888,7 +1978,7 @@ int32_t main(int argc, char *argv[]) } } - if(SMART_ATTR_AUTOSAVE_FEATURE_FLAG) + if (SMART_ATTR_AUTOSAVE_FEATURE_FLAG) { switch (enable_Disable_SMART_Attribute_Autosave(&deviceList[deviceIter], SMART_ATTR_AUTOSAVE_FEATURE_STATE_FLAG)) { @@ -1896,7 +1986,7 @@ int32_t main(int argc, char *argv[]) if (VERBOSITY_QUIET < toolVerbosity) { printf("Successfully "); - if(SMART_ATTR_AUTOSAVE_FEATURE_STATE_FLAG) + if (SMART_ATTR_AUTOSAVE_FEATURE_STATE_FLAG) { printf("Enabled"); } @@ -1986,9 +2076,9 @@ int32_t main(int argc, char *argv[]) } } - if (PROGRESS_CHAR != NULL) + if (PROGRESS_CHAR != M_NULLPTR) { - int result = UNKNOWN; + eReturnValues result = UNKNOWN; //first take whatever was entered in progressTest and convert it to uppercase to do fewer string comparisons convert_String_To_Upper_Case(progressTest); //do some string comparisons to figure out what we are checking for progress on @@ -2005,7 +2095,7 @@ int32_t main(int argc, char *argv[]) else if (strcmp(progressTest, "IDD") == 0) { uint8_t iddStatus = 0; - char iddStatusString[MAX_DST_STATUS_STRING_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, iddStatusString, MAX_DST_STATUS_STRING_LENGTH + 1); if (VERBOSITY_QUIET < toolVerbosity) { printf("Getting IDD progress.\n"); @@ -2042,7 +2132,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -2072,11 +2162,11 @@ void utility_Usage(bool shortUsage) printf("\t%s --%s\n", util_name, SCAN_LONG_OPT_STRING); printf("\t%s -d %s -%c\n", util_name, deviceHandleExample, DEVICE_INFO_SHORT_OPT); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, SAT_INFO_LONG_OPT_STRING); - printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, LOWLEVEL_INFO_LONG_OPT_STRING); + printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, LOWLEVEL_INFO_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, SMART_CHECK_LONG_OPT_STRING); printf("\t%s -d %s --%s --%s\n", util_name, deviceHandleExample, SHORT_DST_LONG_OPT_STRING, CAPTIVE_LONG_OPT_STRING); printf("\t%s -d %s --%s --%s\n", util_name, deviceHandleExample, CONVEYANCE_DST_LONG_OPT_STRING, POLL_LONG_OPT_STRING); - printf("\t%s -d %s --%s --%s\n", util_name, deviceHandleExample, LONG_DST_LONG_OPT_STRING, POLL_LONG_OPT_STRING); + printf("\t%s -d %s --%s --%s\n", util_name, deviceHandleExample, LONG_DST_LONG_OPT_STRING, POLL_LONG_OPT_STRING); printf("\t%s -d %s --%s short\n", util_name, deviceHandleExample, IDD_TEST_LONG_OPT_STRING); printf("\t%s -d %s --%s long --%s\n", util_name, deviceHandleExample, IDD_TEST_LONG_OPT_STRING, CAPTIVE_LONG_OPT_STRING); printf("\t%s -d %s --%s\n", util_name, deviceHandleExample, ABORT_DST_LONG_OPT_STRING); @@ -2093,11 +2183,11 @@ void utility_Usage(bool shortUsage) printf("\t%s -d %s --%s summary --%s raw\n", util_name, deviceHandleExample, SHOW_SMART_ERROR_LOG_LONG_OPT_STRING, SMART_ERROR_LOG_FORMAT_LONG_OPT_STRING); printf("\t%s -d %s --%s g --%s bfi\n", util_name, deviceHandleExample, SCSI_DEFECTS_LONG_OPT_STRING, SCSI_DEFECTS_DESCRIPTOR_MODE_LONG_OPT_STRING); printf("\t%s -d %s --%s --%s 40\n", util_name, deviceHandleExample, DST_AND_CLEAN_LONG_OPT_STRING, ERROR_LIMIT_LONG_OPT_STRING); - + //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("Utility Options\n"); @@ -2157,6 +2247,7 @@ void utility_Usage(bool shortUsage) print_SMART_Attributes_Help(shortUsage); print_SMART_Attribute_Autosave_Help(shortUsage); print_SMART_Auto_Offline_Help(shortUsage); + print_SMART_Offline_Data_Collection_Help(shortUsage); print_Show_SMART_Error_Log_Help(shortUsage); print_SMART_Error_Log_Format_Help(shortUsage); print_SMART_Info_Help(shortUsage); diff --git a/utils/C/openSeaChest/openSeaChest_Sample.c b/utils/C/openSeaChest/openSeaChest_Sample.c index 77284932..badad6d2 100644 --- a/utils/C/openSeaChest/openSeaChest_Sample.c +++ b/utils/C/openSeaChest/openSeaChest_Sample.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,13 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -28,7 +31,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Sample"; -const char *buildVersion = "1.2.1"; +const char *buildVersion = "1.3.0"; //////////////////////////// // functions to declare // @@ -48,14 +51,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -63,12 +66,12 @@ int32_t main(int argc, char *argv[]) LICENSE_VAR ECHO_COMMAND_LINE_VAR SCAN_FLAG_VAR - NO_BANNER_VAR + NO_BANNER_VAR AGRESSIVE_SCAN_FLAG_VAR SHOW_BANNER_VAR SHOW_HELP_VAR TEST_UNIT_READY_VAR - FAST_DISCOVERY_VAR + FAST_DISCOVERY_VAR MODEL_MATCH_VARS FW_MATCH_VARS CHILD_MODEL_MATCH_VARS @@ -85,7 +88,7 @@ int32_t main(int argc, char *argv[]) #endif LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -97,7 +100,7 @@ int32_t main(int argc, char *argv[]) SAT_INFO_LONG_OPT, USB_CHILD_INFO_LONG_OPT, SCAN_LONG_OPT, - NO_BANNER_OPT, + NO_BANNER_OPT, AGRESSIVE_SCAN_LONG_OPT, SCAN_FLAGS_LONG_OPT, VERSION_LONG_OPT, @@ -106,7 +109,7 @@ int32_t main(int argc, char *argv[]) LICENSE_LONG_OPT, ECHO_COMMAND_LIN_LONG_OPT, TEST_UNIT_READY_LONG_OPT, - FAST_DISCOVERY_LONG_OPT, + FAST_DISCOVERY_LONG_OPT, ONLY_SEAGATE_LONG_OPT, MODEL_MATCH_LONG_OPT, FW_MATCH_LONG_OPT, @@ -156,26 +159,26 @@ int32_t main(int argc, char *argv[]) { case 0: //parse long options that have no short option and required arguments here - if (strncmp(longopts[optionIndex].name, "longOption", M_Min(strlen(longopts[optionIndex].name), strlen("longOption"))) == 0) + if (strcmp(longopts[optionIndex].name, "longOption") == 0) { //set flags } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -244,9 +247,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -283,7 +287,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -294,7 +298,7 @@ int32_t main(int argc, char *argv[]) if ((VERBOSITY_QUIET < toolVerbosity) && !NO_BANNER_FLAG) { - openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); + openseachest_utility_Info(util_name, buildVersion, OPENSEA_TRANSPORT_VERSION); } if (SHOW_BANNER_FLAG) @@ -304,7 +308,7 @@ int32_t main(int argc, char *argv[]) if (LICENSE_FLAG) { - print_EULA_To_Screen(false, false); + print_EULA_To_Screen(); } if (SCAN_FLAG || AGRESSIVE_SCAN_FLAG) @@ -380,7 +384,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -436,6 +440,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -465,7 +471,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -485,10 +491,10 @@ int32_t main(int argc, char *argv[]) flags = DO_NOT_WAKE_DRIVE; } - if (FAST_DISCOVERY_FLAG) - { - flags = FAST_SCAN; - } + if (FAST_DISCOVERY_FLAG) + { + flags = FAST_SCAN; + } //set flags that can be passed down in get device regarding forcing specific ATA modes. if (FORCE_ATA_PIO_FLAG) @@ -508,7 +514,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -537,13 +543,13 @@ int32_t main(int argc, char *argv[]) printf("Unable to get device list\n"); } if (!is_Running_Elevated()) - { - exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); - } - else - { - exit(UTIL_EXIT_OPERATION_FAILURE); - } + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } } } } @@ -556,11 +562,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -584,7 +590,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -596,15 +602,15 @@ int32_t main(int argc, char *argv[]) printf("Error: Could not open handle to %s\n", HANDLE_LIST[handleIter]); } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); - if(ret == PERMISSION_DENIED || !is_Running_Elevated()) - { - exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); - } - else - { - exit(UTIL_EXIT_OPERATION_FAILURE); - } - } + if (ret == PERMISSION_DENIED || !is_Running_Elevated()) + { + exit(UTIL_EXIT_NEED_ELEVATED_PRIVILEGES); + } + else + { + exit(UTIL_EXIT_OPERATION_FAILURE); + } + } } } free_Handle_List(&HANDLE_LIST, DEVICE_LIST_COUNT); @@ -626,7 +632,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -651,7 +657,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -690,6 +696,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -755,7 +770,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -789,7 +804,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); @@ -808,7 +823,7 @@ void utility_Usage(bool shortUsage) print_Help_Help(shortUsage); print_License_Help(shortUsage); print_Model_Match_Help(shortUsage); - print_No_Banner_Help(shortUsage); + print_No_Banner_Help(shortUsage); print_Firmware_Revision_Match_Help(shortUsage); print_Only_Seagate_Help(shortUsage); print_Quiet_Help(shortUsage, util_name); @@ -827,7 +842,7 @@ void utility_Usage(bool shortUsage) print_Agressive_Scan_Help(shortUsage); print_SAT_Info_Help(shortUsage); print_Test_Unit_Ready_Help(shortUsage); - print_Fast_Discovery_Help(shortUsage); + print_Fast_Discovery_Help(shortUsage); //utility tests/operations go here - alphabetized //multiple interfaces diff --git a/utils/C/openSeaChest/openSeaChest_Security.c b/utils/C/openSeaChest/openSeaChest_Security.c index 26dbe9c1..a9ea77a2 100644 --- a/utils/C/openSeaChest/openSeaChest_Security.c +++ b/utils/C/openSeaChest/openSeaChest_Security.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,14 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "math_utils.h" + #include "getopt.h" #include "EULA.h" #include "ata_helper.h" //for defined ATA security password size of 32bytes @@ -43,7 +47,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_Security"; -const char *buildVersion = "3.3.0"; +const char *buildVersion = "3.4.1"; typedef enum _eSeaChestSecurityExitCodes { @@ -69,14 +73,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -136,7 +140,7 @@ int32_t main(int argc, char *argv[]) ATA_SECURITY_FREEZELOCK_OP_VAR LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -238,7 +242,7 @@ int32_t main(int argc, char *argv[]) //parse long options that have no short option and required arguments here if (strcmp(longopts[optionIndex].name, CONFIRM_LONG_OPT_STRING) == 0) { - if (strlen(optarg) == strlen(DATA_ERASE_ACCEPT_STRING) && strncmp(optarg, DATA_ERASE_ACCEPT_STRING, strlen(DATA_ERASE_ACCEPT_STRING)) == 0) + if (strcmp(optarg, DATA_ERASE_ACCEPT_STRING) == 0) { DATA_ERASE_FLAG = true; } @@ -292,7 +296,7 @@ int32_t main(int argc, char *argv[]) snprintf(TCG_PSID_FLAG, TCG_PSID_BUF_LEN, "%s", optarg); } #endif //#if !defined(DISABLE_TCG_SUPPORT) - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_MODIFICATIONS_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "byteswap") == 0) { @@ -376,7 +380,7 @@ int32_t main(int argc, char *argv[]) ATA_SECURITY_PASSWORD_MODIFICATIONS.md5Hash = true; } #endif - //TODO: handle other modifications + //handle other modifications //TODO: handle bad combinations of modifications else { @@ -384,7 +388,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_PASSWORD_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_PASSWORD_LONG_OPT_STRING) == 0) { ATA_SECURITY_USER_PROVIDED_PASS = true; if (strcmp(optarg, "empty") == 0) @@ -395,24 +399,23 @@ int32_t main(int argc, char *argv[]) } else if (strcmp(optarg, "SeaChest") == 0) { - ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, strlen("SeaChest")); - memcpy(ATA_SECURITY_PASSWORD, "SeaChest", strlen("SeaChest")); + ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, safe_strlen("SeaChest")); + memcpy(ATA_SECURITY_PASSWORD, "SeaChest", safe_strlen("SeaChest")); } else { //If the user quoted their password when putting on the cmdline, then we can accept spaces. Otherwise spaces cannot be picked up. - //TODO: If comma separated values were given, then we need to parse the input differently!!! - if (strlen(optarg) > ATA_SECURITY_MAX_PW_LENGTH) + if (safe_strlen(optarg) > ATA_SECURITY_MAX_PW_LENGTH) { print_Error_In_Cmd_Line_Args(ATA_SECURITY_PASSWORD_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } //printf("User entered \"%s\" for their password\n", optarg); - memcpy(ATA_SECURITY_PASSWORD, optarg, M_Min(strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH));//make sure we don't try copying over a null terminator because we just need to store the 32bytes of characters provided. - ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, M_Min(strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH)); + memcpy(ATA_SECURITY_PASSWORD, optarg, M_Min(safe_strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH));//make sure we don't try copying over a null terminator because we just need to store the 32bytes of characters provided. + ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, M_Min(safe_strlen(optarg), ATA_SECURITY_MAX_PW_LENGTH)); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_USING_MASTER_PW_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "master") == 0) { @@ -430,7 +433,7 @@ int32_t main(int argc, char *argv[]) } } #if defined ENABLE_ATA_SET_PASSWORD - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_MASTER_PW_CAPABILITY_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "high") == 0) { @@ -447,18 +450,16 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING) == 0) { - uint64_t masterIDOut = 0; - if (!get_And_Validate_Integer_Input(optarg, &masterIDOut)) + if (!get_And_Validate_Integer_Input_Uint16(optarg, M_NULLPTR, &ATA_SECURITY_MASTER_PW_ID)) { print_Error_In_Cmd_Line_Args(ATA_SECURITY_MASTER_PW_ID_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } - ATA_SECURITY_MASTER_PW_ID = C_CAST(uint16_t, masterIDOut); } #endif //ENABLE_ATA_SET_PASSWORD - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_FORCE_SAT_LONG_OPT_STRING) == 0) { ATA_SECURITY_FORCE_SAT_VALID = true; if (strcmp(optarg, "enable") == 0) @@ -477,7 +478,7 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ATA_SECURITY_ERASE_OP_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ATA_SECURITY_ERASE_OP_LONG_OPT_STRING) == 0) { ATA_SECURITY_ERASE_OP = true; if (strcmp(optarg, "enhanced") == 0) @@ -496,38 +497,43 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); } else if (strcmp(longopts[optionIndex].name, DISPLAY_LBA_LONG_OPT_STRING) == 0) { - DISPLAY_LBA_FLAG = true; - if (0 == sscanf(optarg, "%" SCNu64, &DISPLAY_LBA_THE_LBA)) + if (get_And_Validate_Integer_Input_Uint64(C_CAST(const char*, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &DISPLAY_LBA_THE_LBA)) + { + DISPLAY_LBA_FLAG = true; + } + else { if (strcmp(optarg, "maxLBA") == 0) { USE_MAX_LBA = true; + DISPLAY_LBA_FLAG = true; } else if (strcmp(optarg, "childMaxLBA") == 0) { USE_CHILD_MAX_LBA = true; + DISPLAY_LBA_FLAG = true; } else { @@ -536,7 +542,7 @@ int32_t main(int argc, char *argv[]) } } } - else if (strncmp(longopts[optionIndex].name, ZERO_VERIFY_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ZERO_VERIFY_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, ZERO_VERIFY_LONG_OPT_STRING) == 0) { ZERO_VERIFY_FLAG = true; if (strcmp(optarg, "full") == 0) @@ -617,9 +623,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -656,7 +663,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -753,10 +760,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); -#if defined (ENABLE_HWRAID_SUPPORT) - scan_And_Print_Raid_Devs(scanControl, NULL); -#endif + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -775,31 +779,34 @@ int32_t main(int argc, char *argv[]) if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceUppercase) { //change all to uppercase - char thePassword[ATA_SECURITY_MAX_PW_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, thePassword, ATA_SECURITY_MAX_PW_LENGTH + 1); memcpy(thePassword, ATA_SECURITY_PASSWORD, ATA_SECURITY_MAX_PW_LENGTH); convert_String_To_Upper_Case(thePassword); memcpy(ATA_SECURITY_PASSWORD, thePassword, ATA_SECURITY_MAX_PW_LENGTH); + explicit_zeroes(thePassword, ATA_SECURITY_MAX_PW_LENGTH); } else if (ATA_SECURITY_PASSWORD_MODIFICATIONS.forceLowercase) { //change all to lowercase - char thePassword[ATA_SECURITY_MAX_PW_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, thePassword, ATA_SECURITY_MAX_PW_LENGTH + 1); memcpy(thePassword, ATA_SECURITY_PASSWORD, ATA_SECURITY_MAX_PW_LENGTH); convert_String_To_Lower_Case(thePassword); memcpy(ATA_SECURITY_PASSWORD, thePassword, ATA_SECURITY_MAX_PW_LENGTH); + explicit_zeroes(thePassword, ATA_SECURITY_MAX_PW_LENGTH); } else if (ATA_SECURITY_PASSWORD_MODIFICATIONS.invertCase) { //swap case from upper to lower and lower to upper. - char thePassword[ATA_SECURITY_MAX_PW_LENGTH + 1] = { 0 }; + DECLARE_ZERO_INIT_ARRAY(char, thePassword, ATA_SECURITY_MAX_PW_LENGTH + 1); memcpy(thePassword, ATA_SECURITY_PASSWORD, ATA_SECURITY_MAX_PW_LENGTH); convert_String_To_Inverse_Case(thePassword); memcpy(ATA_SECURITY_PASSWORD, thePassword, ATA_SECURITY_MAX_PW_LENGTH); + explicit_zeroes(thePassword, ATA_SECURITY_MAX_PW_LENGTH); } //check if byteswapping what was entered if (ATA_SECURITY_PASSWORD_MODIFICATIONS.byteSwapped) { - for (uint8_t iter = 0; iter < ATA_SECURITY_MAX_PW_LENGTH; iter += 2) + for (uint8_t iter = 0; (iter + 1) < ATA_SECURITY_MAX_PW_LENGTH; iter += 2) { uint8_t temp = ATA_SECURITY_PASSWORD[iter + 1]; ATA_SECURITY_PASSWORD[iter + 1] = ATA_SECURITY_PASSWORD[iter]; @@ -814,7 +821,7 @@ int32_t main(int argc, char *argv[]) else if (ATA_SECURITY_PASSWORD_MODIFICATIONS.rightAligned) { //memcpy and memset based on how many characters were provided by the caller. - memmove(&ATA_SECURITY_PASSWORD[ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT], &ATA_SECURITY_PASSWORD[0], ATA_SECURITY_PASSWORD_BYTE_COUNT); + safe_memmove(&ATA_SECURITY_PASSWORD[ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT], ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT, &ATA_SECURITY_PASSWORD[0], ATA_SECURITY_PASSWORD_BYTE_COUNT); memset(&ATA_SECURITY_PASSWORD[0], 0, ATA_SECURITY_MAX_PW_LENGTH - ATA_SECURITY_PASSWORD_BYTE_COUNT); } //now check if we had padding to add. NOTE: if right aligned, padding mshould be added IN FRONT (left side) @@ -855,8 +862,8 @@ int32_t main(int argc, char *argv[]) else { //user did not set a password, so we need to set "SeaChest" - ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, strlen("SeaChest")); - memcpy(ATA_SECURITY_PASSWORD, "SeaChest", strlen("SeaChest")); + ATA_SECURITY_PASSWORD_BYTE_COUNT = C_CAST(uint8_t, safe_strlen("SeaChest")); + memcpy(ATA_SECURITY_PASSWORD, "SeaChest", safe_strlen("SeaChest")); } //print out errors for unknown arguments for remaining args that haven't been processed yet @@ -903,8 +910,10 @@ int32_t main(int argc, char *argv[]) } exit(UTIL_EXIT_INVALID_DEVICE_HANDLE); } - + if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -953,7 +962,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -996,7 +1005,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -1044,11 +1053,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -1073,7 +1082,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -1115,7 +1124,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1140,7 +1149,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1180,6 +1189,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -1259,7 +1277,7 @@ int32_t main(int argc, char *argv[]) if (ZERO_VERIFY_FLAG) { - ret = zero_Verify_Test(&deviceList[deviceIter], ZERO_VERIFY_MODE_FLAG, HIDE_LBA_COUNTER); + ret = zero_Verify_Test(&deviceList[deviceIter], C_CAST(eZeroVerifyTestType, ZERO_VERIFY_MODE_FLAG), HIDE_LBA_COUNTER); switch (ret) { case SUCCESS: @@ -1287,7 +1305,7 @@ int32_t main(int argc, char *argv[]) if (DISPLAY_LBA_FLAG) { - uint8_t *displaySector = C_CAST(uint8_t*, calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); + uint8_t *displaySector = C_CAST(uint8_t*, safe_calloc_aligned(deviceList[deviceIter].drive_info.deviceBlockSize, sizeof(uint8_t), deviceList[deviceIter].os_info.minimumAlignment)); if (!displaySector) { perror("Could not allocate memory to read LBA."); @@ -1303,15 +1321,15 @@ int32_t main(int argc, char *argv[]) } if (SUCCESS == read_LBA(&deviceList[deviceIter], DISPLAY_LBA_THE_LBA, false, displaySector, deviceList[deviceIter].drive_info.deviceBlockSize)) { - printf("\nContents of LBA %"PRIu64":\n", DISPLAY_LBA_THE_LBA); + printf("\nContents of LBA %" PRIu64 ":\n", DISPLAY_LBA_THE_LBA); print_Data_Buffer(displaySector, deviceList[deviceIter].drive_info.deviceBlockSize, true); } else { - printf("Error Reading LBA %"PRIu64" for display\n", DISPLAY_LBA_THE_LBA); + printf("Error Reading LBA %" PRIu64 " for display\n", DISPLAY_LBA_THE_LBA); exitCode = UTIL_EXIT_OPERATION_FAILURE; } - safe_Free_aligned(displaySector) + safe_free_aligned(&displaySector); } #if !defined(DISABLE_TCG_SUPPORT) @@ -1355,7 +1373,7 @@ int32_t main(int argc, char *argv[]) } } - if (strlen(TCG_SID_FLAG) > 0 && strlen(TCG_SID_FLAG) < 32) + if (safe_strlen(TCG_SID_FLAG) > 0 && safe_strlen(TCG_SID_FLAG) < 32) { if (toolVerbosity > VERBOSITY_QUIET) { @@ -1378,7 +1396,7 @@ int32_t main(int argc, char *argv[]) printf("unlocked\n"); } } - switch (set_Port_State(&deviceList[deviceIter], TCG_PORT_FIRMWARE_DOWNLOAD, FWDL_PORT_MODE_FLAG, TCG_PORT_AUTHENTICATION_SID, TCG_SID_FLAG, NULL)) + switch (set_Port_State(&deviceList[deviceIter], TCG_PORT_FIRMWARE_DOWNLOAD, FWDL_PORT_MODE_FLAG, TCG_PORT_AUTHENTICATION_SID, TCG_SID_FLAG, M_NULLPTR)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1419,7 +1437,7 @@ int32_t main(int argc, char *argv[]) } //TODO: Seagate HDD and SAS SSD only { - switch (set_Port_State(&deviceList[deviceIter], TCG_PORT_IEEE_1667, IEEE1667_PORT_MODE_FLAG, TCG_PORT_AUTHENTICATION_SID, TCG_SID_FLAG, NULL)) + switch (set_Port_State(&deviceList[deviceIter], TCG_PORT_IEEE_1667, IEEE1667_PORT_MODE_FLAG, TCG_PORT_AUTHENTICATION_SID, TCG_SID_FLAG, M_NULLPTR)) { case SUCCESS: if (VERBOSITY_QUIET < toolVerbosity) @@ -1480,7 +1498,7 @@ int32_t main(int argc, char *argv[]) } if (DATA_ERASE_FLAG) { - if (strlen(TCG_PSID_FLAG) == 0) + if (safe_strlen(TCG_PSID_FLAG) == 0) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1488,7 +1506,7 @@ int32_t main(int argc, char *argv[]) } return UTIL_EXIT_ERROR_IN_COMMAND_LINE; } - else if (strlen(TCG_PSID_FLAG) < 32) + else if (safe_strlen(TCG_PSID_FLAG) < 32) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1546,11 +1564,11 @@ int32_t main(int argc, char *argv[]) if (DATA_ERASE_FLAG) { eRevertAuthority authority = REVERT_AUTHORITY_MSID; - char *passwordToUse = NULL; - if (strlen(TCG_PSID_FLAG) || strlen(TCG_SID_FLAG)) + char *passwordToUse = M_NULLPTR; + if (safe_strlen(TCG_PSID_FLAG) || safe_strlen(TCG_SID_FLAG)) { //user is providing SID or PSID to use. - if (strlen(TCG_PSID_FLAG) > 0 && strlen(TCG_PSID_FLAG) < 32) + if (safe_strlen(TCG_PSID_FLAG) > 0 && safe_strlen(TCG_PSID_FLAG) < 32) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -1558,12 +1576,12 @@ int32_t main(int argc, char *argv[]) } return UTIL_EXIT_ERROR_IN_COMMAND_LINE; } - else if (strlen(TCG_PSID_FLAG) == 32) + else if (safe_strlen(TCG_PSID_FLAG) == 32) { authority = REVERT_AUTHORITY_PSID; passwordToUse = TCG_PSID_FLAG; } - else if (strlen(TCG_SID_FLAG) > 0) + else if (safe_strlen(TCG_SID_FLAG) > 0) { authority = REVERT_AUTHORITY_SID; passwordToUse = TCG_SID_FLAG; @@ -1763,7 +1781,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1806,7 +1824,7 @@ void utility_Usage(bool shortUsage) printf("\nReturn codes\n"); printf("============\n"); int totalErrorCodes = SEACHEST_SECURITY_EXIT_MAX_ERROR - SEACHEST_SECURITY_EXIT_ZERO_VALIDATION_FAILURE; - ptrToolSpecificxitCode seachestSecurityExitCodes = C_CAST(ptrToolSpecificxitCode, calloc(totalErrorCodes, sizeof(toolSpecificxitCode))); + ptrToolSpecificxitCode seachestSecurityExitCodes = C_CAST(ptrToolSpecificxitCode, safe_calloc(int_to_sizet(totalErrorCodes), sizeof(toolSpecificxitCode))); //now set up all the exit codes and their meanings if (seachestSecurityExitCodes) { @@ -1818,7 +1836,7 @@ void utility_Usage(bool shortUsage) case SEACHEST_SECURITY_EXIT_ZERO_VALIDATION_FAILURE: snprintf(seachestSecurityExitCodes[exitIter - UTIL_TOOL_SPECIFIC_STARTING_ERROR_CODE].exitCodeString, TOOL_EXIT_CODE_STRING_MAX_LENGTH, "Zero Validation Failure"); break; - //TODO: add more exit codes here! + //add more exit codes here! default://We shouldn't ever hit the default case! break; } diff --git a/utils/C/openSeaChest/openSeaChest_ZBD.c b/utils/C/openSeaChest/openSeaChest_ZBD.c index 8fdb9864..58e724b0 100644 --- a/utils/C/openSeaChest/openSeaChest_ZBD.c +++ b/utils/C/openSeaChest/openSeaChest_ZBD.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // // Do NOT modify or remove this copyright and license // -// Copyright (c) 2014-2022 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +// Copyright (c) 2014-2024 Seagate Technology LLC and/or its Affiliates, All Rights Reserved // // This software is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,11 +15,14 @@ ////////////////////// // Included files // ////////////////////// -#include "common.h" -#include <ctype.h> -#if defined (__unix__) || defined(__APPLE__) //using this definition because linux and unix compilers both define this. Apple does not define this, which is why it has it's own definition -#include <unistd.h> -#endif +#include "common_types.h" +#include "type_conversion.h" +#include "memory_safety.h" +#include "string_utils.h" +#include "io_utils.h" +#include "unit_conversion.h" +#include "math_utils.h" + #include "getopt.h" #include "EULA.h" #include "openseachest_util_options.h" @@ -29,7 +33,7 @@ // Global Variables // //////////////////////// const char *util_name = "openSeaChest_ZBD"; -const char *buildVersion = "2.2.2"; +const char *buildVersion = "2.3.0"; //////////////////////////// // functions to declare // @@ -49,14 +53,14 @@ static void utility_Usage(bool shortUsage); //! \return exitCode = error code returned by the application // //----------------------------------------------------------------------------- -int32_t main(int argc, char *argv[]) +int main(int argc, char *argv[]) { ///////////////// // Variables // ///////////////// //common utility variables - int ret = SUCCESS; - eUtilExitCodes exitCode = UTIL_EXIT_NO_ERROR; + eReturnValues ret = SUCCESS; + int exitCode = UTIL_EXIT_NO_ERROR; DEVICE_UTIL_VARS DEVICE_INFO_VAR SAT_INFO_VAR @@ -90,7 +94,7 @@ int32_t main(int argc, char *argv[]) #endif LOWLEVEL_INFO_VAR - int args = 0; + int args = 0; int argIndex = 0; int optionIndex = 0; @@ -168,7 +172,7 @@ int32_t main(int argc, char *argv[]) { case 0: //parse long options that have no short option and required arguments here - if (strncmp(longopts[optionIndex].name, ZONE_ID_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(ZONE_ID_LONG_OPT_STRING))) == 0) + if (strcmp(longopts[optionIndex].name, ZONE_ID_LONG_OPT_STRING) == 0) { if (strcmp(optarg, "all") == 0) { @@ -176,27 +180,22 @@ int32_t main(int argc, char *argv[]) } else { - if (!get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &ZONE_ID_FLAG)) + if (!get_And_Validate_Integer_Input_Uint64(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &ZONE_ID_FLAG)) { print_Error_In_Cmd_Line_Args(ZONE_ID_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } } - else if (strncmp(longopts[optionIndex].name, MAX_ZONES_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MAX_ZONES_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MAX_ZONES_LONG_OPT_STRING) == 0) { - uint64_t temp = 0; - if (get_And_Validate_Integer_Input(C_CAST(const char *, optarg), &temp)) - { - MAX_ZONES_FLAG = C_CAST(uint32_t, temp); - } - else + if (!get_And_Validate_Integer_Input_Uint32(C_CAST(const char *, optarg), M_NULLPTR, ALLOW_UNIT_NONE, &MAX_ZONES_FLAG)) { print_Error_In_Cmd_Line_Args(MAX_ZONES_LONG_OPT_STRING, optarg); exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, REPORT_ZONES_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(REPORT_ZONES_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, REPORT_ZONES_LONG_OPT_STRING) == 0) { REPORT_ZONES_FLAG = true; if (strcmp(optarg, "all") == 0) @@ -249,22 +248,22 @@ int32_t main(int argc, char *argv[]) exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } } - else if (strncmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, MODEL_MATCH_LONG_OPT_STRING) == 0) { MODEL_MATCH_FLAG = true; snprintf(MODEL_STRING_FLAG, MODEL_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, FW_MATCH_LONG_OPT_STRING) == 0) { FW_MATCH_FLAG = true; snprintf(FW_STRING_FLAG, FW_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_MODEL_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_MODEL_MATCH_LONG_OPT_STRING) == 0) { CHILD_MODEL_MATCH_FLAG = true; snprintf(CHILD_MODEL_STRING_FLAG, CHILD_MATCH_STRING_LENGTH, "%s", optarg); } - else if (strncmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING, M_Min(strlen(longopts[optionIndex].name), strlen(CHILD_FW_MATCH_LONG_OPT_STRING))) == 0) + else if (strcmp(longopts[optionIndex].name, CHILD_FW_MATCH_LONG_OPT_STRING) == 0) { CHILD_FW_MATCH_FLAG = true; snprintf(CHILD_FW_STRING_FLAG, CHILD_FW_MATCH_STRING_LENGTH, "%s", optarg); @@ -333,9 +332,10 @@ int32_t main(int argc, char *argv[]) SHOW_BANNER_FLAG = true; break; case VERBOSE_SHORT_OPT: //verbose - if (optarg != NULL) + if (!set_Verbosity_From_String(optarg, &toolVerbosity)) { - toolVerbosity = atoi(optarg); + print_Error_In_Cmd_Line_Args_Short_Opt(VERBOSE_SHORT_OPT, optarg); + exit(UTIL_EXIT_ERROR_IN_COMMAND_LINE); } break; case QUIET_SHORT_OPT: //quiet mode @@ -372,7 +372,7 @@ int32_t main(int argc, char *argv[]) int commandLineIter = 1;//start at 1 as starting at 0 means printing the directory info+ SeaChest.exe (or ./SeaChest) for (commandLineIter = 1; commandLineIter < argc; commandLineIter++) { - if (strncmp(argv[commandLineIter], "--echoCommandLine", strlen(argv[commandLineIter])) == 0) + if (strcmp(argv[commandLineIter], "--echoCommandLine") == 0) { continue; } @@ -469,7 +469,7 @@ int32_t main(int argc, char *argv[]) { scanControl |= SCAN_SEAGATE_ONLY; } - scan_And_Print_Devs(scanControl, NULL, toolVerbosity); + scan_And_Print_Devs(scanControl, toolVerbosity); } // Add to this if list anything that is suppose to be independent. // e.g. you can't say enumerate & then pull logs in the same command line. @@ -525,6 +525,8 @@ int32_t main(int argc, char *argv[]) } if ((FORCE_SCSI_FLAG && FORCE_ATA_FLAG) + || (FORCE_SCSI_FLAG && FORCE_NVME_FLAG) + || (FORCE_ATA_FLAG && FORCE_NVME_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG && FORCE_ATA_UDMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_DMA_FLAG) || (FORCE_ATA_PIO_FLAG && FORCE_ATA_UDMA_FLAG) @@ -559,7 +561,7 @@ int32_t main(int argc, char *argv[]) } uint64_t flags = 0; - DEVICE_LIST = C_CAST(tDevice*, calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); + DEVICE_LIST = C_CAST(tDevice*, safe_calloc(DEVICE_LIST_COUNT, sizeof(tDevice))); if (!DEVICE_LIST) { if (VERBOSITY_QUIET < toolVerbosity) @@ -602,7 +604,7 @@ int32_t main(int argc, char *argv[]) if (RUN_ON_ALL_DRIVES && !USER_PROVIDED_HANDLE) { - //TODO? check for this flag ENABLE_LEGACY_PASSTHROUGH_FLAG. Not sure it is needed here and may not be desirable. + for (uint32_t devi = 0; devi < DEVICE_LIST_COUNT; ++devi) { DEVICE_LIST[devi].deviceVerbosity = toolVerbosity; @@ -650,11 +652,11 @@ int32_t main(int argc, char *argv[]) deviceList[handleIter].sanity.size = sizeof(tDevice); deviceList[handleIter].sanity.version = DEVICE_BLOCK_VERSION; #if defined (UEFI_C_SOURCE) - deviceList[handleIter].os_info.fd = NULL; + deviceList[handleIter].os_info.fd = M_NULLPTR; #elif !defined(_WIN32) deviceList[handleIter].os_info.fd = -1; #if defined(VMK_CROSS_COMP) - deviceList[handleIter].os_info.nvmeFd = NULL; + deviceList[handleIter].os_info.nvmeFd = M_NULLPTR; #endif #else deviceList[handleIter].os_info.fd = INVALID_HANDLE_VALUE; @@ -678,7 +680,7 @@ int32_t main(int argc, char *argv[]) if ((deviceList[handleIter].os_info.fd < 0) || #else if (((deviceList[handleIter].os_info.fd < 0) && - (deviceList[handleIter].os_info.nvmeFd == NULL)) || + (deviceList[handleIter].os_info.nvmeFd == M_NULLPTR)) || #endif (ret == FAILURE || ret == PERMISSION_DENIED)) #else @@ -720,7 +722,7 @@ int32_t main(int argc, char *argv[]) //check for model number match if (MODEL_MATCH_FLAG) { - if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == NULL) + if (strstr(deviceList[deviceIter].drive_info.product_identification, MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -745,7 +747,7 @@ int32_t main(int argc, char *argv[]) //check for child model number match if (CHILD_MODEL_MATCH_FLAG) { - if (strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == NULL) + if (safe_strlen(deviceList[deviceIter].drive_info.bridge_info.childDriveMN) == 0 || strstr(deviceList[deviceIter].drive_info.bridge_info.childDriveMN, CHILD_MODEL_STRING_FLAG) == M_NULLPTR) { if (VERBOSITY_QUIET < toolVerbosity) { @@ -785,6 +787,15 @@ int32_t main(int argc, char *argv[]) deviceList[deviceIter].drive_info.drive_type = ATA_DRIVE; } + if (FORCE_NVME_FLAG) + { + if (VERBOSITY_QUIET < toolVerbosity) + { + printf("\tForcing NVME Drive\n"); + } + deviceList[deviceIter].drive_info.drive_type = NVME_DRIVE; + } + if (FORCE_ATA_PIO_FLAG) { if (VERBOSITY_QUIET < toolVerbosity) @@ -871,7 +882,7 @@ int32_t main(int argc, char *argv[]) { ZONE_ID_FLAG = 0; } - switch (close_Zone(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG)) + switch (close_Zone(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG, 0)) { case SUCCESS: if (toolVerbosity > VERBOSITY_QUIET) @@ -882,7 +893,7 @@ int32_t main(int argc, char *argv[]) } else { - printf("Successfully closed zone %"PRIu64"\n", ZONE_ID_FLAG); + printf("Successfully closed zone %" PRIu64 "\n", ZONE_ID_FLAG); } } break; @@ -919,7 +930,7 @@ int32_t main(int argc, char *argv[]) { ZONE_ID_FLAG = 0; } - switch (finish_Zone(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG)) + switch (finish_Zone(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG, 0)) { case SUCCESS: if (toolVerbosity > VERBOSITY_QUIET) @@ -930,7 +941,7 @@ int32_t main(int argc, char *argv[]) } else { - printf("Successfully finished zone %"PRIu64"\n", ZONE_ID_FLAG); + printf("Successfully finished zone %" PRIu64 "\n", ZONE_ID_FLAG); } } break; @@ -967,7 +978,7 @@ int32_t main(int argc, char *argv[]) { ZONE_ID_FLAG = 0; } - switch (open_Zone(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG)) + switch (open_Zone(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG, 0)) { case SUCCESS: if (toolVerbosity > VERBOSITY_QUIET) @@ -978,7 +989,7 @@ int32_t main(int argc, char *argv[]) } else { - printf("Successfully opened zone %"PRIu64"\n", ZONE_ID_FLAG); + printf("Successfully opened zone %" PRIu64 "\n", ZONE_ID_FLAG); } } break; @@ -1015,7 +1026,7 @@ int32_t main(int argc, char *argv[]) { ZONE_ID_FLAG = 0; } - switch (reset_Write_Pointer(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG)) + switch (reset_Write_Pointer(&deviceList[deviceIter], ZONE_ID_ALL_FLAG, ZONE_ID_FLAG, 0)) { case SUCCESS: if (toolVerbosity > VERBOSITY_QUIET) @@ -1026,7 +1037,7 @@ int32_t main(int argc, char *argv[]) } else { - printf("Successfully reset write pointer for zone %"PRIu64"\n", ZONE_ID_FLAG); + printf("Successfully reset write pointer for zone %" PRIu64 "\n", ZONE_ID_FLAG); } } break; @@ -1054,20 +1065,20 @@ int32_t main(int argc, char *argv[]) { ZONE_ID_FLAG = 0; } - if (SUCCESS == get_Number_Of_Zones(&deviceList[deviceIter], REPORT_ZONES_REPORTING_MODE_FLAG, ZONE_ID_FLAG, &numberOfZones)) + if (SUCCESS == get_Number_Of_Zones(&deviceList[deviceIter], C_CAST(eZoneReportingOptions, REPORT_ZONES_REPORTING_MODE_FLAG), ZONE_ID_FLAG, &numberOfZones)) { numberOfZones = M_Min(MAX_ZONES_FLAG, numberOfZones); - ptrZoneDescriptor zoneDescriptors = C_CAST(ptrZoneDescriptor, calloc(numberOfZones, sizeof(zoneDescriptor))); + ptrZoneDescriptor zoneDescriptors = C_CAST(ptrZoneDescriptor, safe_calloc(numberOfZones, sizeof(zoneDescriptor))); if (!zoneDescriptors) { perror("cannot allocate memory for zone descriptors"); exit(UTIL_EXIT_OPERATION_FAILURE); } - int reportRet = get_Zone_Descriptors(&deviceList[deviceIter], REPORT_ZONES_REPORTING_MODE_FLAG, ZONE_ID_FLAG, numberOfZones, zoneDescriptors); + eReturnValues reportRet = get_Zone_Descriptors(&deviceList[deviceIter], C_CAST(eZoneReportingOptions, REPORT_ZONES_REPORTING_MODE_FLAG), ZONE_ID_FLAG, numberOfZones, zoneDescriptors); switch (reportRet) { case SUCCESS: - print_Zone_Descriptors(REPORT_ZONES_REPORTING_MODE_FLAG, numberOfZones, zoneDescriptors); + print_Zone_Descriptors(C_CAST(eZoneReportingOptions, REPORT_ZONES_REPORTING_MODE_FLAG), numberOfZones, zoneDescriptors); break; case NOT_SUPPORTED: exitCode = UTIL_EXIT_OPERATION_NOT_SUPPORTED; @@ -1078,7 +1089,7 @@ int32_t main(int argc, char *argv[]) printf("Failed to get zones to report!\n"); break; } - safe_Free(zoneDescriptors); + safe_free_zone_descriptor(&zoneDescriptors); } else { @@ -1089,7 +1100,7 @@ int32_t main(int argc, char *argv[]) //At this point, close the device handle since it is no longer needed. Do not put any further IO below this. close_Device(&deviceList[deviceIter]); } - safe_Free(DEVICE_LIST); + free_device_list(&DEVICE_LIST); exit(exitCode); } @@ -1130,7 +1141,7 @@ void utility_Usage(bool shortUsage) //return codes printf("\nReturn codes\n"); printf("============\n"); - print_SeaChest_Util_Exit_Codes(0, NULL, util_name); + print_SeaChest_Util_Exit_Codes(0, M_NULLPTR, util_name); //utility options - alphabetized printf("\nUtility Options\n"); diff --git a/whitesource.config b/whitesource.config new file mode 100644 index 00000000..e1a8feb5 --- /dev/null +++ b/whitesource.config @@ -0,0 +1,2 @@ +fileSystemScan=true +includes=**/*c **/*cc **/*cp **/*cpp **/*cxx **/*c++ **/*h **/*hh **/*hpp **/*hxx **/*h++ **/*m **/*mm **/*pch **/*c# **/*cs **/*csharp **/*go **/*goc **/*js **/*pl **/*plx **/*pm **/*ph **/*cgi **/*fcgi **/*pod **/*psgi **/*al **/*perl **/*t **/*pl6 **/*p6m **/*p6l **/*pm6 **/*nqp **/*6pl **/*6pm **/*p6 **/*php **/*py **/*rb **/*swift **/*java **/*clj **/*cljx **/*cljs **/*cljc **/*jar **/*egg **/*dll **/*tar.gz **/*tgz **/*zip **/*whl **/*gem **/*apk **/*air **/*dmg **/*exe **/*gem **/*gzip **/*msi **/*nupkg **/*swc **/*swf **/tar.bz2 **/pkg.tar.xz **/(u)?deb **/(a)?rpm