diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 84c2c94d83b..e7de8d198e7 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -5,62 +5,31 @@ jobs: build-job: name: Build runs-on: ubuntu-latest - if: "!contains(github.event.commits[0].message, '[skip ci]')" strategy: matrix: - include: - - model: "dsl-ax82u" - sdk: "src-rt-5.02axhnd.675x" - ui: "default" - skip: "n" - - model: "rt-ax82u" - sdk: "src-rt-5.02axhnd.675x" - ui: "default" - skip: "n" - - model: "rt-ax82u_v2" - sdk: "src-rt-5.04axhnd.675x" - ui: "default" - skip: "n" - - model: "rt-ax92u" - sdk: "src-rt-5.02axhnd" - ui: "default" - skip: "n" - - model: "rt-ax5400" - sdk: "src-rt-5.04axhnd.675x" - ui: "default" - skip: "n" - - model: "tuf-ax3000" - sdk: "src-rt-5.02axhnd.675x" - ui: "default" - skip: "n" - - model: "tuf-ax5400" - sdk: "src-rt-5.02axhnd.675x" - ui: "default" - skip: "n" - - model: "tuf-ax3000" - sdk: "src-rt-5.02axhnd.675x" - ui: "tuf" - skip: "n" - - model: "tuf-ax5400" - sdk: "src-rt-5.02axhnd.675x" - ui: "tuf" - skip: "n" - - model: "rt-ax95q" - sdk: "src-rt-5.02axhnd.675x" - ui: "default" - skip: "n" - - model: "rt-axe95q" - sdk: "src-rt-5.02axhnd.675x" - ui: "default" - skip: "n" - container: + cfg: + - { model: "rt-ax92u", sdk: "src-rt-5.02axhnd", ui: "default", skip: false } + - { model: "dsl-ax82u", sdk: "src-rt-5.02axhnd.675x", ui: "default", skip: false } + - { model: "tuf-ax5400", sdk: "src-rt-5.02axhnd.675x", ui: "default", skip: false } + - { model: "tuf-ax5400", sdk: "src-rt-5.02axhnd.675x", ui: "tuf", skip: false } + - { model: "tuf-ax3000", sdk: "src-rt-5.02axhnd.675x", ui: "default", skip: false } + - { model: "tuf-ax3000", sdk: "src-rt-5.02axhnd.675x", ui: "tuf", skip: false } + - { model: "rt-ax82u", sdk: "src-rt-5.02axhnd.675x", ui: "default", skip: false } + - { model: "rt-ax95q", sdk: "src-rt-5.02axhnd.675x", ui: "default", skip: false } + - { model: "rt-axe95q", sdk: "src-rt-5.02axhnd.675x", ui: "default", skip: false } + - { model: "rt-ax82u_v2", sdk: "src-rt-5.04axhnd.675x", ui: "default", skip: false } + - { model: "rt-ax5400", sdk: "src-rt-5.04axhnd.675x", ui: "default", skip: false } + - { model: "tuf-ax3000_v2", sdk: "src-rt-5.04axhnd.675x", ui: "default", skip: false } + - { model: "tuf-ax3000_v2", sdk: "src-rt-5.04axhnd.675x", ui: "tuf", skip: false } + if: "!contains(github.event.commits[0].message, '[SKIP_CI]')" + container: image: gnuton/asuswrt-merlin-toolchains-docker:latest env: MERLINUPDATE: "y" - MODEL: ${{ matrix.model }} - SDK: ${{ matrix.sdk }} - UI: ${{ matrix.ui }} - SKIP_BUILD: ${{ matrix.skip }} + MODEL: ${{ matrix.cfg.model }} + SDK: ${{ matrix.cfg.sdk }} + UI: ${{ matrix.cfg.ui }} + SKIP_BUILD: ${{ matrix.cfg.skip }} GIT_REPO: "https://github.com/gnuton/asuswrt-merlin.ng.git" PROJECT_DIR: "/project/asuswrt-merlin.ng" CHANGELOG_FILE: "/tmp/CHANGELOG" @@ -69,20 +38,37 @@ jobs: - ${{ github.workspace }}:/project steps: - name: Fix permissions in docker image + if: matrix.cfg.skip == false run: | sudo chown docker:docker /github/home /home/docker /project -R - name: Setup git config + if: matrix.cfg.skip == false run: | - # setup the username and email. I tend to use 'GitHub Actions Bot' with no email by default git config --global user.email "bot@gnuton.org" git config --global user.name "Circle CI BOT" git config --global push.default simple - - name: "Fetch code" + - name: "Fetch code" + if: matrix.cfg.skip == false run: | cd /project - git clone --single-branch --depth 1 --branch master $GIT_REPO + if [[ $GITHUB_REF_TYPE == "tag" ]]; then + export BRANCH="master" + else + export BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" + fi + + echo "Fetching code from branch $BRANCH" + + if git clone --single-branch --depth 1 --branch "$BRANCH" "$GIT_REPO"; then + echo "Code fetched successfully." + else + echo "Failed to fetch code. Check the repository and branch settings." + exit 1 + fi + ls /home/docker - name: "Set version" + if: matrix.cfg.skip == false run: | cd ${PROJECT_DIR} export CIRCLE_TAG="${GITHUB_REF#refs/*/}" @@ -97,11 +83,13 @@ jobs: echo "Release detected. Updating version.conf with MAJOR_VER=${MAJOR_VER} and MINOR_VER=${MINOR_VER}" fi - name: Generate changelog + if: matrix.cfg.skip == false run: | cd ${PROJECT_DIR} python tools/get-last-notes.py > "${CHANGELOG_FILE}" cat "${CHANGELOG_FILE}" - name: "Build" + if: matrix.cfg.skip == false run: | echo "----- I am: $(id) -----" cd ${PROJECT_DIR}/release/${SDK} @@ -130,27 +118,21 @@ jobs: echo "Enabling TUF UI" sed -i 's/TUF_UI=n/TUF_UI=y/' ${PROJECT_DIR}/release/src-rt/target.mak fi - echo "----- BUILD -----" - if [[ ${SKIP_BUILD} == "Y" ]]; then - echo "Skipping build" - exit 0 - fi - make ${MODEL} + + echo "----- BUILD ${MODEL}-----" + make "${MODEL}" # #### Just for testing #### # mkdir -p "${PROJECT_DIR}/release/${SDK}/image/" # echo "TEST" > "${PROJECT_DIR}/release/${SDK}/image/${MODEL}_${UI}_puresqubi.w" - name: "Prepare artifacts" + if: matrix.cfg.skip == false env: ARTIFACTS_DIR: ${{ github.workspace }}/artifacts run: | export IMAGE_PATH=${PROJECT_DIR}/release/${SDK}/image/ mkdir -p "${ARTIFACTS_DIR}" - if [[ ${SKIP_BUILD} == "Y" ]]; then - echo "Nothing to persist. Skipping." - exit 0 - fi echo "Removing images with boot loader." rm -rf ${IMAGE_PATH}/*cferom* @@ -176,11 +158,11 @@ jobs: cp "${CHANGELOG_FILE}" "${ARTIFACTS_DIR}" fi - name: "Archive artifacts" + if: matrix.cfg.skip == false uses: actions/upload-artifact@v2 with: - name: release-${{ matrix.model }}-${{ matrix.ui }} + name: release-${{ matrix.cfg.model }}-${{ matrix.cfg.ui }} path: ${{ github.workspace }}/artifacts - release-job: name: Publish needs: build-job @@ -221,7 +203,7 @@ jobs: git config --global user.name "Circle CI BOT" git config --global push.default simple - name: Download packages - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: "Publish Manifest" env: UPDATE_DIR: "updates" @@ -238,11 +220,12 @@ jobs: echo "RT-AX5400#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt echo "TUF-AX5400#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt echo "TUF-AX3000#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt + echo "TUF-AX3000_V2#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt echo "RT-AX95Q#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt echo "RT-AXE95Q#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt echo "RT-AX5400#FW${MAJOR_VER}#EXT${MINOR_VER}" >> ${UPDATE_DIR}/manifest2.txt cp ${CHANGELOG_FILE} ${UPDATE_DIR}/"${RELEASE_NOTE_FILE}" echo "Uploading to github manifest and ${RELEASE_NOTE_FILE}" git add ${UPDATE_DIR} - git commit -m "Updating Notes and manifest to version:${MAJOR_VER} ${MINOR_VER} [skip ci]" -a + git commit -m "Updating Notes and manifest to version:${MAJOR_VER} ${MINOR_VER} [SKIP_CI]" -a git push origin diff --git a/.gitignore b/.gitignore index 9f11b755a17..9133cb4288a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -.idea/ +.idea/checkstyle-idea.xml +.idea/dbnavigator.xml +.idea/workspace.xml + diff --git a/release/src-rt-5.04axhnd.675x/bcmdrivers/broadcom/net/wl/impl87/main/components/apps/acsdv2/prebuilt/TUF-AX3000_V2/acs_cli2 b/release/src-rt-5.04axhnd.675x/bcmdrivers/broadcom/net/wl/impl87/main/components/apps/acsdv2/prebuilt/TUF-AX3000_V2/acs_cli2 new file mode 100755 index 00000000000..602669af415 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bcmdrivers/broadcom/net/wl/impl87/main/components/apps/acsdv2/prebuilt/TUF-AX3000_V2/acs_cli2 differ diff --git a/release/src-rt-5.04axhnd.675x/bcmdrivers/broadcom/net/wl/impl87/main/components/apps/acsdv2/prebuilt/TUF-AX3000_V2/acsd2 b/release/src-rt-5.04axhnd.675x/bcmdrivers/broadcom/net/wl/impl87/main/components/apps/acsdv2/prebuilt/TUF-AX3000_V2/acsd2 new file mode 100755 index 00000000000..bd7b7aaf062 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bcmdrivers/broadcom/net/wl/impl87/main/components/apps/acsdv2/prebuilt/TUF-AX3000_V2/acsd2 differ diff --git a/release/src-rt-5.04axhnd.675x/bcmdrivers/opensource/phy/prebuilt/TUF-AX3000_V2 b/release/src-rt-5.04axhnd.675x/bcmdrivers/opensource/phy/prebuilt/TUF-AX3000_V2 new file mode 120000 index 00000000000..52d60f673fe --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/bcmdrivers/opensource/phy/prebuilt/TUF-AX3000_V2 @@ -0,0 +1 @@ +arm_6756hnd \ No newline at end of file diff --git a/release/src-rt-5.04axhnd.675x/bcmdrivers/opensource/phy/prebuilt/arm_6756hnd/gpy211.o b/release/src-rt-5.04axhnd.675x/bcmdrivers/opensource/phy/prebuilt/arm_6756hnd/gpy211.o new file mode 100755 index 00000000000..efa8cddbcdb Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bcmdrivers/opensource/phy/prebuilt/arm_6756hnd/gpy211.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/board/broadcom/bcmbca/board.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/board/broadcom/bcmbca/board.o new file mode 100755 index 00000000000..b0722d518a4 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/board/broadcom/bcmbca/board.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/board/broadcom/bcmbca/board_sdk.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/board/broadcom/bcmbca/board_sdk.o new file mode 100755 index 00000000000..f3116333fd0 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/board/broadcom/bcmbca/board_sdk.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/common/autoboot.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/common/autoboot.o new file mode 100755 index 00000000000..149837dbe9d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/common/autoboot.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/drivers/net/bcmbca/phy/dt_parsing.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/drivers/net/bcmbca/phy/dt_parsing.o new file mode 100755 index 00000000000..5ef6b3d35a2 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/drivers/net/bcmbca/phy/dt_parsing.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/arp.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/arp.o new file mode 100755 index 00000000000..09a7eae2c0d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/arp.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/net.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/net.o new file mode 100755 index 00000000000..38a598b6325 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/net.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/ping.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/ping.o new file mode 100755 index 00000000000..56d996b54b0 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/ping.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/tftp.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/tftp.o new file mode 100755 index 00000000000..2673f2b6b9a Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/emmc_spl/net/tftp.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/board/broadcom/bcmbca/board.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/board/broadcom/bcmbca/board.o new file mode 100755 index 00000000000..636f64f3e2d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/board/broadcom/bcmbca/board.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/board/broadcom/bcmbca/board_sdk.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/board/broadcom/bcmbca/board_sdk.o new file mode 100755 index 00000000000..a26bd6d0a6b Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/board/broadcom/bcmbca/board_sdk.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/common/autoboot.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/common/autoboot.o new file mode 100755 index 00000000000..cb211776b0e Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/common/autoboot.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/drivers/net/bcmbca/phy/dt_parsing.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/drivers/net/bcmbca/phy/dt_parsing.o new file mode 100755 index 00000000000..5ef6b3d35a2 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/drivers/net/bcmbca/phy/dt_parsing.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/arp.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/arp.o new file mode 100755 index 00000000000..09a7eae2c0d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/arp.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/net.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/net.o new file mode 100755 index 00000000000..d0ad4eeabaf Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/net.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/ping.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/ping.o new file mode 100755 index 00000000000..71bd8e1c44c Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/ping.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/tftp.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/tftp.o new file mode 100755 index 00000000000..5cc371fa788 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/nand_spl/net/tftp.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/board/broadcom/bcmbca/board.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/board/broadcom/bcmbca/board.o new file mode 100755 index 00000000000..636f64f3e2d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/board/broadcom/bcmbca/board.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/board/broadcom/bcmbca/board_sdk.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/board/broadcom/bcmbca/board_sdk.o new file mode 100755 index 00000000000..c34d5c227bc Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/board/broadcom/bcmbca/board_sdk.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/common/autoboot.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/common/autoboot.o new file mode 100755 index 00000000000..db7f0a300d6 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/common/autoboot.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/drivers/net/bcmbca/phy/dt_parsing.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/drivers/net/bcmbca/phy/dt_parsing.o new file mode 100755 index 00000000000..5ef6b3d35a2 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/drivers/net/bcmbca/phy/dt_parsing.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/arp.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/arp.o new file mode 100755 index 00000000000..09a7eae2c0d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/arp.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/net.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/net.o new file mode 100755 index 00000000000..4e2db287e98 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/net.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/ping.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/ping.o new file mode 100755 index 00000000000..25bef8e4b4c Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/ping.o differ diff --git a/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/tftp.o b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/tftp.o new file mode 100755 index 00000000000..3f9065f110d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/bootloaders/obj.tuf-ax3000_v2/uboot/net/tftp.o differ diff --git a/release/src-rt-5.04axhnd.675x/hostTools/prebuilt/TUF-AX3000_V2/addvtoken b/release/src-rt-5.04axhnd.675x/hostTools/prebuilt/TUF-AX3000_V2/addvtoken new file mode 100755 index 00000000000..565838eeb2b Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/hostTools/prebuilt/TUF-AX3000_V2/addvtoken differ diff --git a/release/src-rt-5.04axhnd.675x/hostTools/prebuilt/TUF-AX3000_V2/lzop b/release/src-rt-5.04axhnd.675x/hostTools/prebuilt/TUF-AX3000_V2/lzop new file mode 100755 index 00000000000..527b9dc8e4d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/hostTools/prebuilt/TUF-AX3000_V2/lzop differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/Makefile new file mode 120000 index 00000000000..22421485087 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/Makefile @@ -0,0 +1 @@ +../../src/router/Makefile \ No newline at end of file diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/acsd/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/acsd/Makefile new file mode 100644 index 00000000000..97adf98b677 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/acsd/Makefile @@ -0,0 +1,9 @@ +all: + +install: + +dynamic: + +clean: + + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/Bcmbuild.mk new file mode 100644 index 00000000000..4e117222b47 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/Bcmbuild.mk @@ -0,0 +1,57 @@ +LIB = libarcher.so + +default: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + +ifneq ($(strip $(BUILD_ARCHERCTL)),) +conditional_build: all +else +conditional_build: + @echo "Skipping $(LIB)" +endif + +ARCH=$(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(HND_SRC)/userspace/private/include \ + -I$(BUILD_DIR)/shared/opensource/include/bcm963xx \ + -I$(BUILD_DIR)/shared/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) + + + +export ARCH CFLAGS LIB_INSTALL_DIR CFLAGS DESKTOP_LINUX BRCM_RELEASETAG + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + +all: + mkdir -p $(INSTALL_DIR)/lib/private/ + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB)* $(FINAL_LIB_INSTALL_DIR) + +clean: + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB)* + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + + +shell: + bash -i + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/Makefile new file mode 100644 index 00000000000..e40b920c259 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/Makefile @@ -0,0 +1,58 @@ + +# Set VPATH because we want to compile in a seperate dir than source. +name := $(lastword $(MAKEFILE_LIST)) +mdir := $(realpath $(dir $(name))) +VPATH=$(mdir) + + +LIB = libarcher.so + +SAVED = $(LIB)_$(ARCH).shipped + +OBJS = archer_api.o + +BRCM_RELEASETAG ?= "unknown" +CFLAGS += -Werror -Wfatal-errors -DBRCM_RELEASETAG=\"$(BRCM_RELEASETAG)\" -I$(HND_SRC)/userspace/private/include -Wno-stringop-truncation + +$(LIB) : + +# from Bcmbuild.mk +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib + +install: $(LIB) + mkdir -p $(LIB_INSTALL_DIR) + install -p -t $(LIB_INSTALL_DIR) $(LIB) + mkdir -p $(INSTALLDIR)/lib + install -p -m 755 -t $(INSTALLDIR)/lib $(LIB) + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(INSTALLDIR)/lib/$(LIB) + +ifneq ($(wildcard $(mdir)/*.c),) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive + +else + +ifneq ($(wildcard prebuilt/libarcher.so),) +$(LIB): + cp prebuilt/libarcher.so libarcher.so +else +$(LIB): $(SAVED) + cat $< > $@ +endif + +endif + +binaryonly_prepare: + -cp $(LIB) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -rf $(mdir)/*.c $(mdir)/*.h + + +# Generate and use dependencies. +CFLAGS += -MD +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/autodetect new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/autodetect @@ -0,0 +1 @@ + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/prebuilt/libarcher.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/prebuilt/libarcher.so new file mode 100755 index 00000000000..699ef0d06e6 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archer_lib/prebuilt/libarcher.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Bcmbuild.mk new file mode 100644 index 00000000000..fed0e907c3f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Bcmbuild.mk @@ -0,0 +1,69 @@ +EXE := archerctl +EXEALT := archer + +all install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH := $(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/bin +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) + +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin$(BCM_INSTALL_SUFFIX_DIR) + +ifneq ($(strip $(BUILD_ARCHERCTL)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + (cd $(FINAL_EXE_INSTALL_DIR); ln -sf $(EXE) $(EXEALT)) + +else + +conditional_build: + @echo "Skipping $(EXE) (not configured)" + +endif + + +clean: clean_legacy + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR)/$(EXEALT) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(EXE) + + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Makefile new file mode 100644 index 00000000000..70cae4f4979 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Makefile @@ -0,0 +1,15 @@ + +EXE = archerctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + mkdir -p $(INSTALL_DIR)/bin + (cd $(INSTALL_DIR)/bin; rm -f archer; ln -s $(EXE) archer) + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Makefile.fullsrc new file mode 100644 index 00000000000..dad6fb5246c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/Makefile.fullsrc @@ -0,0 +1,20 @@ +OBJS := archer_ctl.o + +LIBS := -L$(HND_SRC)/router-sysdep/archer_lib/ -larcher + + +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) \ + -Wl,-unresolved-symbols=ignore-in-shared-libs,-rpath,$(CMS_LIB_RPATH) \ + $(CMS_LIB_PATH) $(LIBS) + + +binaryonly_prepare: + -cp $(EXE) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include -Wno-stringop-truncation +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/autodetect new file mode 100644 index 00000000000..86dc0b1bf02 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/autodetect @@ -0,0 +1,2 @@ + +dependson: private/libs/archer diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/prebuilt/archerctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/prebuilt/archerctl new file mode 100755 index 00000000000..df572982714 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/prebuilt/archerctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/scripts/hw_accel_dump.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/scripts/hw_accel_dump.sh new file mode 100644 index 00000000000..e1656f1be0d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/archerctl/scripts/hw_accel_dump.sh @@ -0,0 +1,188 @@ +#!/bin/sh +# +# hw_accel_dump.sh +# + +LOOP_TIME=10 +NR_RUNS=0 +NR_REPEATS=1 +DUMP_CLEAR=0 +DUMP_DMESG=0 +DUMP_FLOW=1 +MAX_PRINT="--all" +# By default disable Wifi dumps and let user specify +RADIOS="" + +show_help () { + echo "Syntax: $0 [-r repeat_count] [-t interval_time_sec] [-c] [-d] [-nfd] [-mpr] [-radio]" + echo "Options:" + echo -e "\t-r repeat_count: Number of iterations of data collection. Default one loop." + echo -e "\t-t interval_time_sec: Sleep time between two intervals. Default 10 sec." + echo -e "\t-c: Clear driver dumps wherever applicable. Default is not clear." + echo -e "\t-d: dmesg -c. Default no dmesg" + echo -e "\t-nfd: noflowdump. Do not dump flows." + echo -e "\t-mpr: maxprint. Provide max flows to dump in decimal" + echo -e "\t-radio: Specify radio index [0-2], Default none" + exit +} + +# Help option +if [[ $# -eq 1 ]] && [[ $1 == "--help" ]]; then + show_help + exit 0 +fi + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -r|--repeatcount) + NR_REPEATS="$2" + shift # past argument + shift # past value + ;; + -c|--clear) + shift # past argument + DUMP_CLEAR=1 + ;; + -t|--timeinterval) + LOOP_TIME="$2" + shift # past argument + shift # past value + ;; + -d|--dmesg) + shift # past argument + DUMP_DMESG=1 + ;; + -nfd|--noflowdump) + shift # past argument + DUMP_FLOW=0 + ;; + -mpr|--maxprint) + MAX_PRINT="--max $2" + shift # past argument + shift # past value + ;; + -radio) + RADIOS="$2" + shift # past argument + shift # past value + ;; + -h|--help) + show_help + exit 0 + ;; + *) # unknown option + echo "Unknown Option $1" + show_help + exit 0; +esac +done + +if ! [ "$LOOP_TIME" -eq "$LOOP_TIME" ] 2>/dev/null; then + echo "Time interval between repeat should be number in sec." + show_help + exit 0; +fi + +if ! [ "$NR_REPEATS" -eq "$NR_REPEATS" ] 2>/dev/null; then + echo "Repeat count should be a number" + show_help + exit 0; +fi + +dump_cmd() { + #echo "=================================" + echo "*** $1 ***" + #echo "=================================" + $1 + echo -e "\n\n" +} + +wifi_dump () { + # dump wifi data path stats + for RADIO_IDX in ${RADIOS} + do + dump_cmd "wl -i wl$RADIO_IDX dpstats" + dump_cmd "dhd -i wl$RADIO_IDX dump" + done + ## +} + +archer_flow_dump () { + ### + + if [[ "$DUMP_FLOW" -eq 1 ]]; then + #dump_cmd "archerctl flows $MAX_PRINT" + dump_cmd "archerctl ucast_l3 $MAX_PRINT" + dump_cmd "archerctl ucast_l2 $MAX_PRINT" + dump_cmd "archerctl mcast $MAX_PRINT" + fi + ### +} +archer_dump () { + + ## + dump_cmd "archerctl status" + dump_cmd "archerctl host" + dump_cmd "archerctl stats" + + ## +} + +stats_dump () { + + ## Wifi dump + wifi_dump + + ## archer dumps + archer_dump + + ## flow-dump + archer_flow_dump + ### +} + +dump_params () { + echo "LOOP_TIME = $LOOP_TIME" + echo "NR_RUNS = $NR_RUNS" + echo "NR_REPEATS = $NR_REPEATS" + echo "DUMP_CLEAR = $DUMP_CLEAR" + echo "DUMP_DMESG = $DUMP_DMESG" + echo "DUMP_FLOW = $DUMP_FLOW" + echo "MAX_PRINT = $MAX_PRINT" + ### +} + +# For script param debugging; Uncomment below +#dump_params + +loop_commands () { + NR_RUNS=`expr $NR_RUNS + 1` + + if [[ $NR_REPEATS != 1 ]]; then + #echo "========================================" + echo " === Iteration $NR_RUNS ===" + #echo "========================================" + fi + + ## Dump Stats/counters + stats_dump + + if [[ "$DUMP_DMESG" -eq 1 ]]; then + dmesg -c + fi + + #if [[ "$DUMP_CLEAR" -eq 1 ]]; then + # Add code here to issue command to clear counters + #fi + + if [[ $NR_REPEATS -gt $NR_RUNS ]]; then + sleep $LOOP_TIME + fi +} + +while [[ $NR_REPEATS -gt $NR_RUNS ]]; do + loop_commands +done diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl/Makefile new file mode 100644 index 00000000000..36088c6f68f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl/Makefile @@ -0,0 +1,13 @@ + +EXE = xtmctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl/autodetect new file mode 100644 index 00000000000..64cb7cbc2ef --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl/autodetect @@ -0,0 +1,3 @@ +condition: ifneq ($(strip $(BUILD_XTMCTL)),) +dependson: private/libs/atmctl public/libs/bcm_boardctl public/libs/bcm_flashutil public/libs/bcm_util public/libs/sys_util public/libs/gen_util + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/Bcmbuild.mk new file mode 100644 index 00000000000..4015bdbd141 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/Bcmbuild.mk @@ -0,0 +1,56 @@ +default: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(subst /userspace, /userspace,$(CURR_DIR)) +BUILD_DIR:=$(word 1, $(BUILD_DIR)) +include $(BUILD_DIR)/make.common + +ifneq ($(strip $(BUILD_XTMCTL)),) +conditional_build: all +else +conditional_build: + @echo "skipping atmctl (not configured)" +endif + +ARCH=$(PROFILE_ARCH) +PREFIX=$(BCM_FSBUILD_DIR)/private/ +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BCM_FSBUILD_DIR)/public/include \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) + +ALLOWED_INCLUDE_PATHS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + + +export ARCH PREFIX OALDIR CFLAGS DESKTOP_LINUX + + +all: + mkdir -p $(INSTALL_DIR)/lib/private/ + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + cp -d $(BCM_FSBUILD_DIR)/private/lib/libatmctl.so* $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + +clean: + rm -f $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR)/libatmctl.so* + -mkdir -p objs/linux + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + + +shell: + bash -i + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/Makefile new file mode 100644 index 00000000000..304f77e10e3 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/Makefile @@ -0,0 +1,13 @@ + +LIB = libatmctl.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/autodetect new file mode 100644 index 00000000000..f156a212c7a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/autodetect @@ -0,0 +1,2 @@ +dependson: public/libs/bcm_util public/libs/bcm_boardctl + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/linux/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/linux/Makefile new file mode 100644 index 00000000000..78cc2f88123 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/atmctl_lib/linux/Makefile @@ -0,0 +1,33 @@ +name := $(lastword $(MAKEFILE_LIST)) +mdir := $(dir $(name)) +VPATH=$(mdir) + +LIB = oal.a +OBJS = xtm.o xtm_trace.o + +ifeq ($(strip $(DESKTOP_LINUX)),y) +OBJS = xtm_desktop.o +endif + +all: $(LIB) + +ifneq ($(wildcard $(mdir)*.c),) +$(LIB) : $(OBJS) + $(AR) -rcs $@ $(OBJS) + +else +$(LIB) : $(LIB)_shipped + echo cp $< $@ + +endif + +clean: + rm -f $(OBJS) *.o *.d $(LIB) + +install: $(LIB) + cp $(LIB) $(PREFIX)/$(LIB) + + +# Generate and use dependencies. +CFLAGS += -MD +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/Bcmbuild.mk new file mode 100644 index 00000000000..72185cf8ccd --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/Bcmbuild.mk @@ -0,0 +1,50 @@ +LIB := libbcm_boardctl.so + +default: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(subst /userspace, /userspace,$(CURR_DIR)) +BUILD_DIR:=$(word 1, $(BUILD_DIR)) +include $(BUILD_DIR)/make.common + + +ARCH=$(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/include +ALLOWED_INCLUDE_PATHS := -I . \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BCM_FSBUILD_DIR)/public/include \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR BUILD_DIR + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + + +all install: clean_legacy + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with dual makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + rm -f linux/*.o linux/*.d linux/oal.a + + +shell: + bash -i diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/Makefile new file mode 100644 index 00000000000..0fca3036b3c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/Makefile @@ -0,0 +1,13 @@ + +LIB = libbcm_boardctl.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/autodetect new file mode 100644 index 00000000000..09247715d79 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/autodetect @@ -0,0 +1 @@ +dependson: public/libs/sys_util public/libs/gen_util public/libs/bcm_util diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/bcm_boardctl.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/bcm_boardctl.h new file mode 100644 index 00000000000..d5536cbaa24 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/bcm_boardctl.h @@ -0,0 +1,205 @@ +/*********************************************************************** + * + * Copyright (c) 2007 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2011:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * + ************************************************************************/ + + +#ifndef __BCM_BOARDCTL_H__ +#define __BCM_BOARDCTL_H__ + +#include +#include "bcm_retcodes.h" +#include "number_defs.h" + +/*!\file bcm_boardctl.h + * \brief Header file for various board ioctls. + * + * These functions are the simple board control functions that other apps, + * including GPL apps, may need. These functions are mostly just wrappers + * around devCtl_boardDriverIoctl(). + * + */ + + +/** Get the board's br0 interface mac address. + * + * @param macAddrNum (OUT) The user must pass in an array of UINT8 of at least + * MAC_ADDR_LEN (6) bytes long. + * + * @return BcmRet enum. + */ +BcmRet devCtl_getBaseMacAddress(UINT8 *macAddrNum); + + +/** Get the available interface mac address. + * + * @param macAddrNum (OUT) The user must pass in an array of UINT8 of at least + * MAC_ADDR_LEN (6) bytes long. + * + * @return BcmRet enum. + */ +BcmRet devCtl_getMacAddress(UINT8 *macAddrNum, UINT32 ulId); + + +/** Get the given number of consecutive available mac addresses. + * + * @param macAddrNum (OUT) The user must pass in an array of UINT8 of at least + * MAC_ADDR_LEN (6) bytes long. + * + * @return BcmRet enum. + */ +BcmRet devCtl_getMacAddresses(UINT8 *macAddrNum, UINT32 ulId, UINT32 num_addresses); + +/** Releases the given number of consecutive mac addresses + * + * @param macAddrNum (OUT) The user must pass in an array of UINT8 of at least + * MAC_ADDR_LEN (6) bytes long. + * + * @return BcmRet enum. + */ +BcmRet devCtl_releaseMacAddresses(UINT8 *macAddrNum, UINT32 num_addresses); + +/** Release the interface mac address that is not used anymore + * + * @param macAddrNum (OUT) The user must pass in an array of UINT8 of at least + * MAC_ADDR_LEN (6) bytes long. + * + * @return BcmRet enum. + */ +BcmRet devCtl_releaseMacAddress(UINT8 *macAddrNum); + + +/** Get the number of ethernet MACS on the system. + * + * @return number of ethernet MACS. + */ +UINT32 devCtl_getNumEnetMacs(void); + + +/** Get the number of ethernet ports on the system. + * + * @return number of ethernet ports. + */ +UINT32 devCtl_getNumEnetPorts(void); + + +/** Get SDRAM size on the system. + * + * @return SDRAM size in number of bytes. + */ +UINT64 devCtl_getSdramSize(void); + + +/** Get the chipId. + * + * This info is used in various places, including CLI and writing new + * flash image. It may be accessed by GPL apps, so it cannot be put + * exclusively in the data model. + * + * @param chipId (OUT) The chip id returned by the kernel. + * @return BcmRet enum. + */ +BcmRet devCtl_getChipId(UINT32 *chipId); + + +#if defined(EPON_SDK_BUILD) +/** Get mac type for a specified uni port + * + * @return success or failure. + */ + +UINT32 devCtl_getPortMacType(unsigned short port, unsigned int *mac_type); + +/** Get the number of FE ports on the system. + * + * @return success or failure. + */ +UINT32 devCtl_getNumFePorts(unsigned int *fe_ports); + +/** Get the number of GE ports on the system. + * + * @return success or failure. + */ +UINT32 devCtl_getNumGePorts(unsigned int *ge_ports); + +/** Get the number of VoIP ports on the system. + * + * @return success or failure. + */ +UINT32 devCtl_getNumVoipPorts(unsigned int *voip_ports); + +/** Get the port_map of internal switch ports used. + * + * @return success or failure. + */ +UINT32 devCtl_getPortMap(unsigned int *port_map); + +#endif /* EPON_SDK_BUILD */ + +/** Get list of all keys/tokenID's in the scratch pad. + * + * @return greater than 0 means number of bytes copied to tokBuf, + * 0 means fail, + * negative number means provided buffer is not big enough and the + * absolute value of the negative number is the number of bytes needed. + */ +SINT32 devCtl_scratchPadList(const char *fileName, char *tokBuf, int bufLen); + +/** Get a buffer from the scratch pad based on tokenId. + * + * @return greater than 0 means number of bytes copied to tokBuf, + * 0 means fail, + * negative number means provided buffer is not big enough and the + * absolute value of the negative number is the number of bytes needed. + */ +SINT32 devCtl_scratchPadGet(const char *fileName, + char *tokenId, char *tokBuf, int bufLen); + +/** Set contents of a scratch pad buffer identified by tokenId. + * + * @return 0 - ok, -1 - fail. + */ +SINT32 devCtl_scratchPadSet(const char *fileName, + char *tokenId, char *tokBuf, int bufLen); + +/** Wipe out the scratchPad. + * + * @return 0 - ok, -1 - fail. + */ +SINT32 devCtl_scratchPadClearAll(const char *fileName); + +/** Read file into given buffer. + */ +SINT32 devCtl_flashReadFile(const char *fileName, char *buf, UINT32 bufLen); + +/** Write buf into fname. + */ +SINT32 devCtl_flashWriteFile(const char *fileName, char *buf, UINT32 bufLen); + +#endif /* __BCM_BOARDCTL_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/bcm_boarddriverctl.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/bcm_boarddriverctl.h new file mode 100644 index 00000000000..6b64564b9b8 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/bcm_boarddriverctl.h @@ -0,0 +1,83 @@ +/*********************************************************************** + * + * Copyright (c) 2007 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2011:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * + ************************************************************************/ + + +#ifndef __BCM_BOARDDRIVERCTL_H__ +#define __BCM_BOARDDRIVERCTL_H__ + +#include +#include "board.h" // for BOARD_IOCTL_ACTION, requires special include path +#include "bcm_retcodes.h" +#include "number_defs.h" +#include "bcm_boardctl.h" + + +/*!\file bcm_boarddriverctl.h + * \brief Header file for various board ioctls. + * + */ + +/** This was the original board driver ioctl function. Despite its name, + * it might actually perform the requested action on a file instead of + * doing a real ioctl to the board driver. Because it may be file based, + * it is now implemented in libbcm_flashutil.so. For simple board ioctls + * which do not involve the config file or scratchpad, look in bcm_boardctl.h. + * + * @param boardIoctl (IN) The ioctl to perform. + * @param action (IN) The sub-action associated with the ioctl. + * @param string (IN) Input data for the ioctl. + * @param strLen (IN) Length of input data. + * @param offset (IN) Offset for the ioctl/sub-action. + * @param data (IN/OUT) Depends on the ioctl/sub-action. Could be used + * to pass in additional data or be used to return data + * from the ioctl. + * @return BcmRet enum. + */ +BcmRet devCtl_boardIoctl(UINT32 boardIoctl, + BOARD_IOCTL_ACTION action, + char *string, + SINT32 strLen, + SINT32 offset, + void *data); + + +/** Do a real ioctl to the board driver. Most callers should probably use + * devCtl_boardIoctl or one of the wrapper functions in bcm_boardctl.h. + */ +BcmRet devCtl_boardDriverIoctl(UINT32 boardIoctl, + BOARD_IOCTL_ACTION action, + char *string, + SINT32 strLen, + SINT32 offset, + void *data); + + +#endif /* __BCM_BOARDDRIVERCTL_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/linux/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/linux/Makefile new file mode 100644 index 00000000000..65a4d66c7cc --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/linux/Makefile @@ -0,0 +1,21 @@ +LIB := oal.a + +OBJS := board.o + +all install: $(LIB) + +clean: + rm -f *.o *.d $(LIB) + +$(LIB) : $(OBJS) + $(AR) -rcs $@ $(OBJS) + + +# Set VPATH because we want to compile in a seperate dir than source. +name := $(lastword $(MAKEFILE_LIST)) +mdir := $(realpath $(dir $(name))) +VPATH=$(mdir) + +# Generate and use dependencies. +CFLAGS += -MD +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/linux/board.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/linux/board.c new file mode 100644 index 00000000000..f3b9d5661e0 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/linux/board.c @@ -0,0 +1,1715 @@ +/*********************************************************************** + * + * <:copyright-BRCM:2006:DUAL/GPL:standard + * + * Copyright (c) 2006 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + * + ************************************************************************/ + +#include /* for open */ +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for ETH_ALEN (MAC_ADDR_LEN) */ +#include +#include "bcm_retcodes.h" +#include "number_defs.h" +#include "board.h" /* for FLASH_ADDR_INFO */ +#include "../bcm_boardctl.h" +#include "../bcm_boarddriverctl.h" +#include "boardparms.h" +#include "bcm_ulog.h" +#include "bcm_fsutils.h" +#include "sysutil_fs.h" + + +#ifdef DESKTOP_LINUX +static int fake_board_ioctl(UINT32 boardIoctl, BOARD_IOCTL_PARMS *ioctlParms); +int fake_kerSysScratchPadList(char *tokBuf, int bufLen); +int fake_kerSysScratchPadGet(char *tokenId, char *tokBuf, int bufLen); +int fake_kerSysScratchPadSet(char *tokenId, char *tokBuf, int bufLen); +int fake_kerSysScratchPadClearAll(void); +char *fake_getSharedBlks(int start_block, int num_blocks); +int fake_setSharedBlks(int start_block, int total_blocks, char *pBuf); +void fake_retriedKfree(char *pShareBuf); +SINT32 fake_kerSysBcmImageSetWhole(UINT8 *buf, SINT32 bufLen); +SINT32 fake_kerSysBcmImageSetCfe(UINT8 *buf, SINT32 bufLen); +SINT32 fake_flashFsKernelImage(UINT8 *buf, SINT32 bufLen); +SINT32 fake_kerSysPersistentSet(UINT8 *buf, UINT32 bufLen); +SINT32 fake_kerSysPersistentGet(UINT8 *buf, UINT32 bufLen); +SINT32 fake_kerSysBackupPsiSet(UINT8 *buf, UINT32 bufLen); +SINT32 fake_kerSysBackupPsiGet(UINT8 *buf, UINT32 bufLen); + + +#define FAKE_FLASH_PSP_FILENAME "flash_persistent_scratch_pad.data" + +/* from bcmdrivers/opensource/include/bcm963xx/board.h */ +/* how many bytes per flash block? */ +#define FAKE_FLASH_BLOCK_SIZE 512 +#define FAKE_NUM_PSP_FLASH_BLOCKS 16 + + +static FLASH_ADDR_INFO fInfo = {0, 0, 0, 0, \ +/* psp start blk, num blks, length in bytes, blk offset from begining,*/ + 0, FAKE_NUM_PSP_FLASH_BLOCKS, FAKE_NUM_PSP_FLASH_BLOCKS*FAKE_FLASH_BLOCK_SIZE, 0, \ + 0, 0, 0, 0, 0, 0, 0 }; + +#endif /* DESKTOP_LINUX */ + + +/* All the devctl functions are probably OS dependent, so they would go here */ + +BcmRet devCtl_getBaseMacAddress(UINT8 *macAddrNum) +{ + return(devCtl_boardDriverIoctl(BOARD_IOCTL_GET_BASE_MAC_ADDRESS, + 0, + (char *) macAddrNum, + ETH_ALEN, + 0, + NULL)); +} + + +BcmRet devCtl_getMacAddress(UINT8 *macAddrNum, UINT32 ulId) +{ + return(devCtl_boardDriverIoctl(BOARD_IOCTL_GET_MAC_ADDRESS, + 0, + (char *) macAddrNum, + ETH_ALEN, + ulId, + NULL)); +} + +BcmRet devCtl_getMacAddresses(UINT8 *macAddrNum, UINT32 ulId, UINT32 num_addresses) +{ + return(devCtl_boardDriverIoctl(BOARD_IOCTL_ALLOC_MAC_ADDRESSES, + 0, + (char *) macAddrNum, + ETH_ALEN, + ulId, + &num_addresses)); +} + +BcmRet devCtl_releaseMacAddresses(UINT8 *macAddrNum, UINT32 num_addresses) +{ + return(devCtl_boardDriverIoctl(BOARD_IOCTL_RELEASE_MAC_ADDRESS, + 0, + (char *) macAddrNum, + ETH_ALEN, + 0, + &num_addresses)); +} + +BcmRet devCtl_releaseMacAddress(UINT8 *macAddrNum) +{ + return(devCtl_boardDriverIoctl(BOARD_IOCTL_RELEASE_MAC_ADDRESS, + 0, + (char *) macAddrNum, + ETH_ALEN, + 0, + NULL)); +} + + +UINT32 devCtl_getNumEnetMacs(void) +{ + UINT32 num; + BcmRet ret; + + ret = devCtl_boardDriverIoctl(BOARD_IOCTL_GET_NUM_ENET_MACS, + 0, NULL, + 0, 0, &num); + return (ret == BCMRET_SUCCESS ? num : 0); +} + + +UINT32 devCtl_getNumEnetPorts(void) +{ + UINT32 num; + BcmRet ret; + + ret = devCtl_boardDriverIoctl(BOARD_IOCTL_GET_NUM_ENET_PORTS, + 0, NULL, + 0, 0, &num); + return (ret == BCMRET_SUCCESS ? num : 0); +} + +#ifndef DESKTOP_LINUX + +/** Open and lock the scratchpad file. Can be blocked if other process + * has the lock already. Allocate buffer and read scratchpad data + * @return file descriptor of the scratchpad file + * negaive number means fail + */ + +int getScratchPadFile(const char *fname, char** ppBuf, UINT32 *bufLen) +{ + struct stat statbuf; + int rc, fd = -1; + int newfile = 0; + mode_t mode = (S_IRUSR | S_IWUSR); + + if ((rc = stat(fname, &statbuf)) < 0) + { + // File does not exist, create it. + newfile = 1; + } + else + { + if (statbuf.st_size != SP_MAX_LEN) + { + // file exists, but is wrong size (don't known when this actually + // happens). Delete it and start a new one. + bcmuLog_error("scratchpad file is wrong size, delete it!"); + rc = unlink(fname); + if (rc < 0) + { + bcmuLog_error("delete of %s failed, errno=%d", fname, errno); + return -1; + } + newfile = 1; + } + else if ((statbuf.st_mode & 07777) != mode) + { + // file exists, is the right size, but wrong file mode (see inode 7). + // fix it. + bcmuLog_error("scratchpad file has wrong permissions, change it!"); + rc = chmod(fname, mode); + if (rc < 0) + { + bcmuLog_error("chmod of %s failed, errno=%d", fname, errno); + // wrong perms is not fatal, so just continue. + } + } + } + + if (newfile) + { + printf("Creating new scratchpad file.\n"); + fd = open(fname, (O_RDWR|O_CREAT), mode); + } + else + { + // open existing file. + fd = open(fname, O_RDWR); + } + if (fd == -1) + { + bcmuLog_error("failed to open %s error %d", fname, errno); + return -1; + } + + /* acquire the file lock for exclusive access , may block if other process has the lock */ + rc = flock(fd, LOCK_EX); + if (rc != 0) + { + bcmuLog_error("failed to lock file %s fd %d rc %d error %d", fname, fd, rc, errno); + close(fd); + return -2; + } + + // *bufLen is always SP_MAX_LEN + *bufLen = SP_MAX_LEN; + *ppBuf = malloc( *bufLen); + if (*ppBuf == NULL) + { + bcmuLog_error("Failed to allocate %d bytes buf", *bufLen); + flock(fd, LOCK_UN); + close(fd); + return -3; + } + + memset(*ppBuf, 0x0, *bufLen); + if (!newfile) + { + rc = read(fd, *ppBuf, *bufLen); + if (rc!= *bufLen) + { + bcmuLog_error("read file expect %d bytes but reurn %d bytes", *bufLen, rc); + flock(fd, LOCK_UN); + close(fd); + free(*ppBuf); + return -4; + } + } + else + { + // This is a new file, so write all 0's into it and also return all + // 0's as the data. + rc = write(fd, *ppBuf, *bufLen); + if (rc != *bufLen) + { + bcmuLog_error("bad write on new file, got %d expected %d", rc, *bufLen); + flock(fd, LOCK_UN); + close(fd); + free(*ppBuf); + return -5; + } + } + + return fd; +} + +/** Free data buffer and unlock and close the scratchpad file. + * @return zero success + * negaive number fail + */ + +int putScratchPadFile(int fd, char* pBuf, UINT32 bufLen, int update) +{ + int rc; + int sts = 0; + + if (update) + { + lseek(fd, 0, SEEK_SET); + rc = write(fd, pBuf, bufLen); + if (rc != bufLen) + { + bcmuLog_error("bad write, got %d expected %d", rc, bufLen); + sts = -1; + } + } + + /* release the file lock first */ + rc = flock(fd, LOCK_UN); + if (rc != 0) + { + bcmuLog_error("failed to unlock fd %d rc %d error %d", fd, rc, errno); + sts = -2; + } + + free(pBuf); + close(fd); + + return sts; +} + +SINT32 devCtl_flashReadFile(const char *fname, char *buf, UINT32 bufLen) +{ + BcmRet ret=BCMRET_SUCCESS; + struct stat statbuf; + int fd, rc; + + rc = stat(fname, &statbuf); + if (rc != 0) + { + bcmuLog_debug("file %s not exist, stat rc=%d", fname, rc); + return BCMRET_INTERNAL_ERROR; + } + if (bufLen > statbuf.st_size) + bufLen = statbuf.st_size; + + fd = open(fname, O_RDONLY); + if (fd < 0) + { + bcmuLog_error("could not open file %s, errno=%d", fname, errno); + return BCMRET_INTERNAL_ERROR; + } + + rc = flock(fd, LOCK_EX); + if( rc != 0 ) + { + bcmuLog_error("failed to lock file %s fd %d rc %d error %d", fname, fd, rc, errno); + close(fd); + return BCMRET_INTERNAL_ERROR; + } + + rc = read(fd, buf, bufLen); + if (rc != bufLen) + { + bcmuLog_error("read error, got %d, expected %d", rc, bufLen); + ret = BCMRET_INTERNAL_ERROR; + } + + flock(fd, LOCK_UN); + close(fd); + + return ret; +} + +SINT32 devCtl_flashWriteFile(const char *fname, char *buf, UINT32 bufLen) +{ + BcmRet ret=BCMRET_SUCCESS; + int fd, rc; + + // Delete the existing file with possible bad mode bits. + // The file might not be there, so don't treat rc < 0 as an error. + rc = unlink(fname); + bcmuLog_debug("unlink of %s returned rc=%d", fname, rc); + + if ((fd = open(fname, (O_RDWR|O_CREAT), (S_IRUSR|S_IWUSR))) < 0) + { + bcmuLog_error("could not open %s for write", fname); + return BCMRET_INTERNAL_ERROR; + } + + rc = flock(fd, LOCK_EX); + if( rc != 0 ) + { + bcmuLog_error("failed to lock file %s fd %d rc %d error %d", fname, fd, rc, errno); + close(fd); + return BCMRET_INTERNAL_ERROR; + } + + rc = write(fd, buf, bufLen); + if (rc < (SINT32) bufLen) + { + bcmuLog_error("write to %s failed, rc=%d", fname, rc); + ret = BCMRET_INTERNAL_ERROR; + } + + flock(fd, LOCK_UN); + close(fd); + + return ret; +} + + +SINT32 devCtl_scratchPadList(const char *fileName, char *tokBuf, int bufLen) +{ + SINT32 sts; + UINT32 spDataLen = 0; + char *pBuf = NULL; + PSP_TOKEN pToken = NULL; + char *startPtr = NULL; + int usedLen; + int tokenNameLen=0; + int copiedLen=0; + int needLen=0; + int fd; + + fd = getScratchPadFile(fileName, &pBuf, &spDataLen); + if( fd < 0 ) + return 0; + + if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) + { + bcmuLog_error("Scratch pad is not initialized"); + if (putScratchPadFile(fd, pBuf, spDataLen, 0) < 0) + { + bcmuLog_error("putScratchPadFile() failed"); + } + return 0; + } + + // Walk through all the tokens + usedLen = sizeof(SP_HEADER); + startPtr = pBuf + sizeof(SP_HEADER); + pToken = (PSP_TOKEN) startPtr; + + while( isalnum(pToken->tokenName[0]) && isascii(pToken->tokenName[0]) && pToken->tokenLen > 0 && + ((usedLen + pToken->tokenLen) <= spDataLen)) + { + tokenNameLen = strlen(pToken->tokenName); + needLen += tokenNameLen + 1; + if (needLen <= bufLen) + { + strcpy(&tokBuf[copiedLen], pToken->tokenName); + copiedLen += tokenNameLen + 1; + } + + usedLen += ((pToken->tokenLen + 0x03) & ~0x03); + startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03); + pToken = (PSP_TOKEN) startPtr; + } + + if ( needLen > bufLen ) + { + // User may purposely pass in a 0 length buffer just to get + // the size, so don't log this as an error. + sts = needLen * (-1); + } + else + { + sts = copiedLen; + } + + if (putScratchPadFile(fd, pBuf, spDataLen, 0) < 0) + { + bcmuLog_error("putScratchPadFile() failed"); + } + + return sts; +} + + +SINT32 devCtl_scratchPadGet(const char *fileName, char *tokenId, char *tokBuf, int bufLen) +{ + UINT32 spDataLen = 0; + PSP_TOKEN pToken = NULL; + char *pBuf = NULL; + char *startPtr = NULL; + int usedLen; + BcmRet sts = 0; + int fd; + + if (NULL == tokenId) + { + return 0; + } + + fd = getScratchPadFile(fileName, &pBuf, &spDataLen); + if( fd < 0 ) + return 0; + + if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) + { + bcmuLog_notice("Scratch pad is not initialized.\n"); + if (putScratchPadFile(fd, pBuf, spDataLen, 0) < 0) + { + bcmuLog_error("putScratchPadFile() failed"); + } + return 0; + } + + // search for the token + usedLen = sizeof(SP_HEADER); + startPtr = pBuf + sizeof(SP_HEADER); + pToken = (PSP_TOKEN) startPtr; + while( isalnum(pToken->tokenName[0]) && isascii(pToken->tokenName[0]) && pToken->tokenLen > 0 && + pToken->tokenLen < spDataLen && usedLen < spDataLen) + { + + if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0) + { + if ( pToken->tokenLen > bufLen ) + { + // User may purposely pass in a 0 length buffer just to get + // the size, so don't log this as an error. + // printk("The length %d of token %s is greater than buffer len %d.\n", pToken->tokenLen, pToken->tokenName, bufLen); + sts = pToken->tokenLen * (-1); + } + else + { + memcpy(tokBuf, startPtr + sizeof(SP_TOKEN), pToken->tokenLen); + sts = pToken->tokenLen; + } + break; + } + + usedLen += ((pToken->tokenLen + 0x03) & ~0x03); + startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03); + pToken = (PSP_TOKEN) startPtr; + } + + if (putScratchPadFile(fd, pBuf, spDataLen, 0) < 0) + { + bcmuLog_error("putScratchPadFile() failed"); + } + + return sts; +} + + +SINT32 devCtl_scratchPadSet(const char *fileName, char *tokenId, char *tokBuf, int bufLen) +{ + UINT32 spDataLen = 0; + PSP_TOKEN pToken = NULL; + char *pBuf = NULL; + SP_HEADER SPHead; + SP_TOKEN SPToken; + char *curPtr; + SINT32 sts = -1; + int tokenNameLen = 0; + int fd; + + if( !tokenId || !isalnum(tokenId[0]) || !isascii(tokenId[0]) ) + { + bcmuLog_error("Invalid scratch pad key name. Must start with an ascii letter or number.\n"); + return sts; + } + + tokenNameLen = strlen(tokenId); + if( tokenNameLen >= TOKEN_NAME_LEN ) + { + bcmuLog_error("Token name length %d large than maximum length %d\n", tokenNameLen, TOKEN_NAME_LEN-1); + return sts; + } + + fd = getScratchPadFile(fileName, &pBuf, &spDataLen); + if( fd < 0 ) + return 0; + + if( bufLen >= (int) (spDataLen - sizeof(SP_HEADER) - sizeof(SP_TOKEN)) ) + { + bcmuLog_error("Scratch pad overflow by %zu bytes. Information not saved.\n", + bufLen - spDataLen - sizeof(SP_HEADER) - + sizeof(SP_TOKEN)); + if (putScratchPadFile(fd, pBuf, spDataLen, 0) < 0) + { + bcmuLog_error("putScratchPadFile() failed"); + } + return sts; + } + + + // form header info. + memset((char *)&SPHead, 0, sizeof(SP_HEADER)); + memcpy(SPHead.SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN); + SPHead.SPVersion = SP_VERSION; + + // form token info. + memset((char*)&SPToken, 0, sizeof(SP_TOKEN)); + strncpy(SPToken.tokenName, tokenId, tokenNameLen); + SPToken.tokenLen = bufLen; + + if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) + { + // new sp, so just flash the token + bcmuLog_notice("No scratch pad found. Initialize scratch pad...\n"); + memset(pBuf, 0x0, spDataLen); + memcpy(pBuf, (char *)&SPHead, sizeof(SP_HEADER)); + curPtr = pBuf + sizeof(SP_HEADER); + memcpy(curPtr, (char *)&SPToken, sizeof(SP_TOKEN)); + curPtr += sizeof(SP_TOKEN); + if( tokBuf ) + memcpy(curPtr, tokBuf, bufLen); + } + else + { + int putAtEnd = 1; + int curLen; + int usedLen; + int skipLen; + + /* Calculate the used length. */ + usedLen = sizeof(SP_HEADER); + curPtr = pBuf + sizeof(SP_HEADER); + pToken = (PSP_TOKEN) curPtr; + skipLen = (pToken->tokenLen + 0x03) & ~0x03; + while( isalnum(pToken->tokenName[0]) && isascii(pToken->tokenName[0]) && + strlen(pToken->tokenName) < TOKEN_NAME_LEN && + pToken->tokenLen > 0 && + pToken->tokenLen < spDataLen && + usedLen < spDataLen ) + { + usedLen += sizeof(SP_TOKEN) + skipLen; + curPtr += sizeof(SP_TOKEN) + skipLen; + pToken = (PSP_TOKEN) curPtr; + skipLen = (pToken->tokenLen + 0x03) & ~0x03; + } + + if( usedLen + SPToken.tokenLen + sizeof(SP_TOKEN) > + spDataLen ) + { + bcmuLog_error("Scratch pad overflow by %d bytes. Information not saved.\n", + (usedLen + SPToken.tokenLen + (int)sizeof(SP_TOKEN)) - + spDataLen); + if (putScratchPadFile(fd, pBuf, spDataLen, 0) < 0) + { + bcmuLog_error("putScratchPadFile() failed"); + } + return sts; + } + + curPtr = pBuf + sizeof(SP_HEADER); + curLen = sizeof(SP_HEADER); + while( curLen < usedLen ) + { + pToken = (PSP_TOKEN) curPtr; + skipLen = (pToken->tokenLen + 0x03) & ~0x03; + if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0) + { + // The token id already exists. + if( tokBuf && pToken->tokenLen == bufLen ) + { + // The length of the new data and the existing data is the + // same. Overwrite the existing data. + memcpy((curPtr+sizeof(SP_TOKEN)), tokBuf, bufLen); + putAtEnd = 0; + } + else + { + // The length of the new data and the existing data is + // different. Shift the rest of the scratch pad to this + // token's location and put this token's data at the end. + char *nextPtr = curPtr + sizeof(SP_TOKEN) + skipLen; + int copyLen = usedLen - (curLen+sizeof(SP_TOKEN) + skipLen); + memcpy( curPtr, nextPtr, copyLen ); + memset( curPtr + copyLen, 0x00, + spDataLen - (curLen + copyLen) ); + usedLen -= sizeof(SP_TOKEN) + skipLen; + } + break; + } + + // get next token + curPtr += sizeof(SP_TOKEN) + skipLen; + curLen += sizeof(SP_TOKEN) + skipLen; + } // end while + + if( putAtEnd ) + { + if( tokBuf ) + { + memcpy( pBuf + usedLen, &SPToken, sizeof(SP_TOKEN) ); + memcpy( pBuf + usedLen + sizeof(SP_TOKEN), tokBuf, bufLen ); + } + memcpy( pBuf, &SPHead, sizeof(SP_HEADER) ); + } + + } + + sts = putScratchPadFile(fd, pBuf, spDataLen, 1); + + return sts; +} + + +SINT32 devCtl_scratchPadClearAll(const char *fileName) +{ + UINT32 spDataLen = 0; + SINT32 sts = -1; + char *pBuf = NULL; + int fd; + + fd = getScratchPadFile(fileName, &pBuf, &spDataLen); + if( fd < 0 ) + return 0; + + memset(pBuf, 0x00, spDataLen); + + sts = putScratchPadFile(fd, pBuf, spDataLen, 1); + + return sts; +} + +#endif /* ifndef DESKTOP_LINUX */ + +#if defined(EPON_SDK_BUILD) +UINT32 devCtl_getNumVoipPorts(unsigned int *voip_ports) +{ + BcmRet ret; + + ret = devCtl_boardDriverIoctl(BOARD_IOCTL_GET_NUM_VOIP_PORTS, + 0, NULL, + 0, 0, voip_ports); + return ret; +} + +#endif /* EPON_SDK_BUILD */ + +UINT64 devCtl_getSdramSize(void) +{ + UINT32 size; + BcmRet ret; +#ifdef DESKTOP_LINUX + size = 32*1024*1024; + ret = BCMRET_SUCCESS; +#else + /* SDRAM size in MB from board driver */ + ret = devCtl_boardDriverIoctl(BOARD_IOCTL_GET_SDRAM_SIZE, + 0, NULL, + 0, 0, &size); +#endif + return (ret == BCMRET_SUCCESS ? ((UINT64)size) << 20: 0); +} + +BcmRet devCtl_getChipId(UINT32 *chipId) +{ + return( devCtl_boardDriverIoctl(BOARD_IOCTL_GET_CHIP_ID, 0, NULL, 0, 0, chipId) ); +} + + +BcmRet devCtl_boardDriverIoctl(UINT32 boardIoctl, + BOARD_IOCTL_ACTION action, + char *string, + SINT32 strLen, + SINT32 offset, + void *data) +{ + BOARD_IOCTL_PARMS ioctlParms; + SINT32 boardFd = 0; + SINT32 rc = 0; + BcmRet ret=BCMRET_SUCCESS; + +#ifdef DESKTOP_LINUX + /* don't open anything, ioctl to this fd will be faked anyways */ + boardFd = 77777; +#else + boardFd = open(BOARD_DEVICE_NAME, O_RDWR); +#endif + + if ( boardFd != -1 ) + { + ioctlParms.string = string; + ioctlParms.strLen = strLen; + ioctlParms.offset = offset; + ioctlParms.action = action; + ioctlParms.buf = data; + ioctlParms.result = -1; + + /* Make sure our strlen is correct for SCRATCHPAD READ/WRITES */ + if (((boardIoctl == BOARD_IOCTL_FLASH_READ) && (ioctlParms.action == SCRATCH_PAD)) || + ((boardIoctl == BOARD_IOCTL_FLASH_WRITE) && (ioctlParms.action == SCRATCH_PAD)) ) + { + if( ioctlParms.string && strlen(ioctlParms.string) && (ioctlParms.strLen == 0) ) + ioctlParms.strLen = strlen(ioctlParms.string); + } + +#ifdef DESKTOP_LINUX + rc = fake_board_ioctl(boardIoctl, &ioctlParms); +#else + rc = ioctl(boardFd, boardIoctl, &ioctlParms); + close(boardFd); +#endif + + /* + * When reading the scratch pad, the return value indicates the count. + * Check for that condition first. + */ + if (((boardIoctl == BOARD_IOCTL_FLASH_READ) && (action == SCRATCH_PAD)) || + ((boardIoctl == BOARD_IOCTL_FLASH_LIST) && (action == SCRATCH_PAD)) || + (boardIoctl == BOARD_IOCTL_BOOT_IMAGE_OPERATION) || + (boardIoctl == BOARD_IOCTL_GET_SEQUENCE_NUMBER)) + { + /* + * The kernel will either return the number of bytes read, + * or if the user provided buffer was not big enough, a + * negative number indicating the number of bytes needed. + */ + ret = (BcmRet)ioctlParms.result; + } + else + { + if (rc < 0) + { + bcmuLog_debug("boardIoctl=0x%x action=%d rc=%d errno=%d", boardIoctl, action, rc, errno); + ret = BCMRET_INVALID_ARGUMENTS; + } + + /* ioctl specific return data */ + if (ret == BCMRET_SUCCESS) + { + if ((boardIoctl == BOARD_IOCTL_GET_PSI_SIZE) || + (boardIoctl == BOARD_IOCTL_GET_BACKUP_PSI_SIZE) || + (boardIoctl == BOARD_IOCTL_GET_SYSLOG_SIZE) || + (boardIoctl == BOARD_IOCTL_GET_CHIP_ID) || + (boardIoctl == BOARD_IOCTL_GET_CHIP_REV) || + (boardIoctl == BOARD_IOCTL_GET_NUM_ENET_MACS) || + (boardIoctl == BOARD_IOCTL_GET_NUM_VOIP_PORTS) || + (boardIoctl == BOARD_IOCTL_GET_NUM_ENET_PORTS) || + (boardIoctl == BOARD_IOCTL_GET_SDRAM_SIZE) || + (boardIoctl == BOARD_IOCTL_GET_BTRM_BOOT) || + (boardIoctl == BOARD_IOCTL_GET_BOOT_SECURE) || + (boardIoctl == BOARD_IOCTL_FLASH_READ && action == FLASH_SIZE) || + (boardIoctl == BOARD_IOCTL_GET_FLASH_TYPE) || + (boardIoctl == BOARD_IOCTL_GETSET_BOOT_INACTIVE_IMAGE)) + { + if (data != NULL) + { + *((UINT32 *)data) = (UINT32) ioctlParms.result; + } + } + } + } + } + else + { + bcmuLog_error("Unable to open device %s", BOARD_DEVICE_NAME); + ret = BCMRET_INTERNAL_ERROR; + } + + return ret; +} + +#ifdef DESKTOP_LINUX + +/** Do first level processing of ioctl. + * + * This function follows the logic of + * bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c:board_ioctl + */ +int fake_board_ioctl(UINT32 command, BOARD_IOCTL_PARMS *ctrlParms) +{ + int ret = 0; + + switch(command) + { + case BOARD_IOCTL_FLASH_WRITE: + + switch(ctrlParms->action) + { + case SCRATCH_PAD: + if (ctrlParms->offset == -1) + ret = fake_kerSysScratchPadClearAll(); + else + ret = fake_kerSysScratchPadSet(ctrlParms->string, ctrlParms->buf, ctrlParms->offset); + break; + + case BCM_IMAGE_WHOLE: + bcmuLog_debug("fake whole image write, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_kerSysBcmImageSetWhole((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; + + case BCM_IMAGE_CFE: + bcmuLog_debug("fake cfe write, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_kerSysBcmImageSetCfe((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; + + case BCM_IMAGE_FS: + bcmuLog_debug("fake fs+kernel write, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_flashFsKernelImage((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; + + case PERSISTENT: + bcmuLog_debug("fake config write, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_kerSysPersistentSet((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; + +#ifdef SUPPORT_BACKUP_PSI + case BACKUP_PSI: + bcmuLog_debug("fake backup config write, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_kerSysBackupPsiSet((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; +#endif + + default: + ret = -EINVAL; + bcmuLog_error("unhandled action %d in BOARD_IOCTL_FLASH_WRITE", ctrlParms->action); + break; + } + + ctrlParms->result = ret; + + break; + + case BOARD_IOCTL_FLASH_READ: + switch (ctrlParms->action) + { + case SCRATCH_PAD: + ret = fake_kerSysScratchPadGet(ctrlParms->string, ctrlParms->buf, ctrlParms->offset); + ctrlParms->result = ret; + break; + + case FLASH_SIZE: + ctrlParms->result = 32 * 1024 * 1024; /* 4 MB? */ + ret = 0; + break; + + case PERSISTENT: + bcmuLog_debug("fake config read, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_kerSysPersistentGet((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; + +#ifdef SUPPORT_BACKUP_PSI + case BACKUP_PSI: + bcmuLog_debug("fake backup psi config read, buf=%p len=%d", ctrlParms->string, ctrlParms->strLen); + ret = fake_kerSysBackupPsiGet((UINT8 *) ctrlParms->string, ctrlParms->strLen); + break; +#endif + + default: + ret = -EINVAL; + ctrlParms->result = ret; + bcmuLog_error("unhandled action %d in BOARD_IOCTL_FLASH_READ", ctrlParms->action); + break; + } + + break; + + case BOARD_IOCTL_FLASH_LIST: + switch (ctrlParms->action) + { + case SCRATCH_PAD: + ret = fake_kerSysScratchPadList(ctrlParms->buf, ctrlParms->offset); + ctrlParms->result = ret; + break; + + default: + ret = -EINVAL; + ctrlParms->result = ret; + bcmuLog_error("unhandled action %d in BOARD_IOCTL_FLASH_READ", ctrlParms->action); + break; + } + + break; + + case BOARD_IOCTL_GET_PSI_SIZE: + ctrlParms->result = 24 * 1024; + ret = 0; + break; + +#ifdef SUPPORT_BACKUP_PSI + case BOARD_IOCTL_GET_BACKUP_PSI_SIZE: + ctrlParms->result = 24 * 1024; + ret = 0; + break; +#endif + + case BOARD_IOCTL_GET_NUM_ENET_MACS: + ctrlParms->result = 2; + ret = 0; + break; + + case BOARD_IOCTL_GET_NUM_ENET_PORTS: + ctrlParms->result = 4; + ret = 0; + break; + + case BOARD_IOCTL_GET_CHIP_ID: +#if defined(CHIP_63138) + ctrlParms->result = 0x63138; +#endif +#if defined(CHIP_63148) + ctrlParms->result = 0x63148; +#endif + + ret = 0; + break; + + case BOARD_IOCTL_GET_CFE_VER: + if (ctrlParms->strLen < 5) + { + bcmuLog_error("buf too short, need 5, got %d", ctrlParms->strLen); + ret = -1; + } + else + { + ctrlParms->string[0] = 1; + ctrlParms->string[1] = 0; + ctrlParms->string[2] = 37; + ctrlParms->string[3] = 9; + ctrlParms->string[4] = 14; + ret = 0; + } + break; + + case BOARD_IOCTL_GET_ID: + /* this is get BOARD_ID */ + { + const char *boardIdStr="DESKTOP_LINUX"; + if (ctrlParms->strLen < (SINT32) (strlen(boardIdStr) + 1)) + { + bcmuLog_error("buf too short, need %zu, got %d", strlen(boardIdStr)+1, ctrlParms->strLen); + ret = -1; + } + else + { + sprintf(ctrlParms->string, "%s", boardIdStr); + ret = 0; + } + } + break; + + case BOARD_IOCTL_GET_BASE_MAC_ADDRESS: + ctrlParms->string[0] = (char) 0; + ctrlParms->string[1] = (char) 0x11; + ctrlParms->string[2] = (char) 0x22; + ctrlParms->string[3] = (char) 0x33; + ctrlParms->string[4] = (char) 0x44; + ctrlParms->string[5] = (char) 0x55; + ret = 0; + break; + + case BOARD_IOCTL_BOOT_IMAGE_OPERATION: + ret = 0; + switch (ctrlParms->offset) + { + case BOOT_SET_PART1_IMAGE: + case BOOT_SET_PART2_IMAGE: + case BOOT_SET_PART1_IMAGE_ONCE: + case BOOT_SET_PART2_IMAGE_ONCE: + case BOOT_SET_OLD_IMAGE: + case BOOT_SET_NEW_IMAGE: + case BOOT_SET_NEW_IMAGE_ONCE: + ctrlParms->result = 0; + break; + + case BOOT_GET_BOOT_IMAGE_STATE: + ctrlParms->result = BOOT_SET_PART1_IMAGE; + break; + + case BOOT_GET_BOOTED_IMAGE_ID: + ctrlParms->result = BOOTED_PART1_IMAGE; + break; + + default: + ret = -EINVAL; + ctrlParms->result = ret; + bcmuLog_error("unhandled offset %d in " + "BOARD_IOCTL_BOOT_IMAGE_OPERATION", ctrlParms->offset); + break; + } + break; + + case BOARD_IOCTL_GET_SEQUENCE_NUMBER: + ctrlParms->result = 0; + break; + + case BOARD_IOCTL_MIPS_SOFT_RESET: + bcmuLog_notice("Soft Reset...\n"); + break; + + default: + ret = -EINVAL; + bcmuLog_error("unhandled board ioctl 0x%x", command); + } + + return ret; +} + + +/** Get list of all keys/tokenID's in the scratch pad. + * + * This function follows the logic of the same function name in + * bcmdrivers/opensource/char/board/bcm963xx/impl1/bcm63xx_flash.c + * + * @return greater than 0 means number of bytes copied to tokBuf, + * 0 means fail, + * negative number means provided buffer is not big enough and the + * absolute value of the negative number is the number of bytes needed. + */ +int fake_kerSysScratchPadList(char *tokBuf, int bufLen) +{ + PSP_TOKEN pToken = NULL; + char *pBuf = NULL; + char *pShareBuf = NULL; + char *startPtr = NULL; + int usedLen; + int tokenNameLen=0; + int copiedLen=0; + int needLen=0; + int sts = 0; + + if (fInfo.flash_scratch_pad_length == 0) + return sts; + + if( (pShareBuf = fake_getSharedBlks(fInfo.flash_scratch_pad_start_blk, + (fInfo.flash_scratch_pad_start_blk + + fInfo.flash_scratch_pad_number_blk))) == NULL ) + { + bcmuLog_error("could not get sharedBlks"); + return sts; + } + + // pBuf points to SP buf + pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset; + + if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) + { + bcmuLog_error("Scratch pad is not initialized.\n"); + fake_retriedKfree(pShareBuf); + return sts; + } + + // Walk through all the tokens + usedLen = sizeof(SP_HEADER); + startPtr = pBuf + sizeof(SP_HEADER); + pToken = (PSP_TOKEN) startPtr; + + while( pToken->tokenName[0] != '\0' && pToken->tokenLen > 0 && + ((usedLen + pToken->tokenLen) <= fInfo.flash_scratch_pad_length)) + { + + tokenNameLen = strlen(pToken->tokenName); + needLen += tokenNameLen + 1; + bcmuLog_debug("found tokenName=%s copiedLen=%d needLen=%d bufLen=%d", pToken->tokenName, copiedLen, needLen, bufLen); + if (needLen <= bufLen) + { + strcpy(&tokBuf[copiedLen], pToken->tokenName); + copiedLen += tokenNameLen + 1; + } + + usedLen += ((pToken->tokenLen + 0x03) & ~0x03); + startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03); + pToken = (PSP_TOKEN) startPtr; + } + + if ( needLen > bufLen ) + { + // User may purposely pass in a 0 length buffer just to get + // the size, so don't log this as an error. + sts = needLen * (-1); + } + else + { + sts = copiedLen; + } + + fake_retriedKfree(pShareBuf); + + return sts; +} + + +/** Get a buffer from the scratch pad based on tokenId. + * + * This function follows the logic of the same function name in + * bcmdrivers/opensource/char/board/bcm963xx/impl1/bcm63xx_flash.c + * + * @return greater than 0 means number of bytes copied to tokBuf, + * 0 means fail, + * negative number means provided buffer is not big enough and the + * absolute value of the negative number is the number of bytes needed. + */ +int fake_kerSysScratchPadGet(char *tokenId, char *tokBuf, int bufLen) +{ + PSP_TOKEN pToken = NULL; + char *pBuf = NULL; + char *pShareBuf = NULL; + char *startPtr = NULL; + int usedLen; + int sts = 0; + + if (fInfo.flash_scratch_pad_length == 0) + return sts; + + if( (pShareBuf = fake_getSharedBlks(fInfo.flash_scratch_pad_start_blk, + (fInfo.flash_scratch_pad_start_blk + + fInfo.flash_scratch_pad_number_blk))) == NULL ) + { + bcmuLog_error("could not get sharedBlks"); + return sts; + } + + // pBuf points to SP buf + pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset; + + if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) + { + bcmuLog_error("Scratch pad is not initialized.\n"); + fake_retriedKfree(pShareBuf); + return sts; + } + + // search for the token + usedLen = sizeof(SP_HEADER); + startPtr = pBuf + sizeof(SP_HEADER); + pToken = (PSP_TOKEN) startPtr; + while( pToken->tokenName[0] != '\0' && pToken->tokenLen > 0 && + pToken->tokenLen < fInfo.flash_scratch_pad_length && + usedLen < fInfo.flash_scratch_pad_length ) + { + + if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0) + { + if ( pToken->tokenLen > bufLen ) + { + bcmuLog_error("The length %d of token %s is greater than buffer len %d.", pToken->tokenLen, pToken->tokenName, bufLen); + sts = pToken->tokenLen * (-1); + } + else + { + bcmuLog_debug("found token %s, copying out (len=%d)", tokenId, pToken->tokenLen); + memcpy(tokBuf, startPtr + sizeof(SP_TOKEN), pToken->tokenLen); + sts = pToken->tokenLen; + } + break; + } + + usedLen += ((pToken->tokenLen + 0x03) & ~0x03); + startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03); + pToken = (PSP_TOKEN) startPtr; + } + + fake_retriedKfree(pShareBuf); + + return sts; +} + + +/** Set contents of a scratch pad buffer identified by tokenId. + * + * This function follows the logic of the same function name in + * bcmdrivers/opensource/char/board/bcm963xx/impl1/bcm63xx_flash.c + * + * @return 0 - ok, -1 - fail. + */ +int fake_kerSysScratchPadSet(char *tokenId, char *tokBuf, int bufLen) +{ + PSP_TOKEN pToken = NULL; + char *pShareBuf = NULL; + char *pBuf = NULL; + SP_HEADER SPHead; + SP_TOKEN SPToken; + char *curPtr; + int sts = -1; + + if (fInfo.flash_scratch_pad_length == 0) + return sts; + + if( bufLen >= (int) (fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) - + sizeof(SP_TOKEN)) ) + { + bcmuLog_error("Scratch pad overflow by %zu bytes. Information not saved.\n", + bufLen - fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) - + sizeof(SP_TOKEN)); + return sts; + } + + if( (pShareBuf = fake_getSharedBlks( fInfo.flash_scratch_pad_start_blk, + (fInfo.flash_scratch_pad_start_blk + + fInfo.flash_scratch_pad_number_blk) )) == NULL ) + { + return sts; + } + + // pBuf points to SP buf + pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset; + + // form header info. + memset((char *)&SPHead, 0, sizeof(SP_HEADER)); + memcpy(SPHead.SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN); + SPHead.SPVersion = SP_VERSION; + + // form token info. + memset((char*)&SPToken, 0, sizeof(SP_TOKEN)); + strncpy(SPToken.tokenName, tokenId, TOKEN_NAME_LEN - 1); + SPToken.tokenLen = bufLen; + + if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) + { + // new sp, so just flash the token + bcmuLog_notice("No scratch pad found. Initialize scratch pad...\n"); + memcpy(pBuf, (char *)&SPHead, sizeof(SP_HEADER)); + curPtr = pBuf + sizeof(SP_HEADER); + memcpy(curPtr, (char *)&SPToken, sizeof(SP_TOKEN)); + curPtr += sizeof(SP_TOKEN); + if( tokBuf ) + memcpy(curPtr, tokBuf, bufLen); + } + else + { + int putAtEnd = 1; + int curLen; + int usedLen; + int skipLen; + + /* Calculate the used length. */ + usedLen = sizeof(SP_HEADER); + curPtr = pBuf + sizeof(SP_HEADER); + pToken = (PSP_TOKEN) curPtr; + skipLen = (pToken->tokenLen + 0x03) & ~0x03; + while( pToken->tokenName[0] >= 'A' && pToken->tokenName[0] <= 'z' && + strlen(pToken->tokenName) < TOKEN_NAME_LEN && + pToken->tokenLen > 0 && + pToken->tokenLen < fInfo.flash_scratch_pad_length && + usedLen < fInfo.flash_scratch_pad_length ) + { + usedLen += sizeof(SP_TOKEN) + skipLen; + curPtr += sizeof(SP_TOKEN) + skipLen; + pToken = (PSP_TOKEN) curPtr; + skipLen = (pToken->tokenLen + 0x03) & ~0x03; + } + + if( usedLen + SPToken.tokenLen + sizeof(SP_TOKEN) > + (UINT32) fInfo.flash_scratch_pad_length ) + { + bcmuLog_error("Scratch pad overflow by %zu bytes. Information not saved.\n", + (usedLen + SPToken.tokenLen + sizeof(SP_TOKEN)) - + fInfo.flash_scratch_pad_length); + /* mwang: did not free pShareBuf, memory leak. */ + return sts; + } + + curPtr = pBuf + sizeof(SP_HEADER); + curLen = sizeof(SP_HEADER); + while( curLen < usedLen ) + { + pToken = (PSP_TOKEN) curPtr; + skipLen = (pToken->tokenLen + 0x03) & ~0x03; + if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0) + { + // The token id already exists. + if( tokBuf && pToken->tokenLen == bufLen ) + { + // The length of the new data and the existing data is the + // same. Overwrite the existing data. + memcpy((curPtr+sizeof(SP_TOKEN)), tokBuf, bufLen); + putAtEnd = 0; + } + else + { + // The length of the new data and the existing data is + // different. Shift the rest of the scratch pad to this + // token's location and put this token's data at the end. + char *nextPtr = curPtr + sizeof(SP_TOKEN) + skipLen; + int copyLen = usedLen - (curLen+sizeof(SP_TOKEN) + skipLen); + memcpy( curPtr, nextPtr, copyLen ); + memset( curPtr + copyLen, 0x00, + fInfo.flash_scratch_pad_length - (curLen + copyLen) ); + usedLen -= sizeof(SP_TOKEN) + skipLen; + } + break; + } + + // get next token + curPtr += sizeof(SP_TOKEN) + skipLen; + curLen += sizeof(SP_TOKEN) + skipLen; + } // end while + + if( putAtEnd ) + { + if( tokBuf ) + { + memcpy( pBuf + usedLen, &SPToken, sizeof(SP_TOKEN) ); + memcpy( pBuf + usedLen + sizeof(SP_TOKEN), tokBuf, bufLen ); + } + memcpy( pBuf, &SPHead, sizeof(SP_HEADER) ); + } + + } // else if not new sp + + sts = fake_setSharedBlks(fInfo.flash_scratch_pad_start_blk, + (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk), + pShareBuf); + + fake_retriedKfree(pShareBuf); + + return sts; +} + + +/** Wipe out the scratchPad. + * + * This function follows the logic of the same function name in + * bcmdrivers/opensource/char/board/bcm963xx/impl1/bcm63xx_flash.c + * + * @return 0 - ok, -1 - fail. + */ +int fake_kerSysScratchPadClearAll(void) +{ + int sts = -1; + char *pShareBuf = NULL; + char *pBuf = NULL; + + + if (fInfo.flash_scratch_pad_length == 0) + return sts; + if( (pShareBuf = fake_getSharedBlks( fInfo.flash_scratch_pad_start_blk, + (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk) )) == NULL ) + return sts; + pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset; + + /* mwang: this actually wipes out the PS_HEADER in the PSP flash area. + * was that the intent? */ + memset(pBuf, 0x00, fInfo.flash_scratch_pad_length); + sts = fake_setSharedBlks(fInfo.flash_scratch_pad_start_blk, + (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk), pBuf); + + fake_retriedKfree(pShareBuf); + + return sts; +} + +/** Return a pointer to the beginning of the requested flash buffer. + * + * On DESKTOP_LINUX, this just opens the fake flash file, allocates a buffer, + * read contents of fake flash file into buffer, and returns pointer to the + * buffer. Persistent flash data is the only thing in the flash file (for now). + * If fake flash file is not present, create one and fill it with zeros. + */ +char *fake_getSharedBlks(int start_block, int num_blocks) +{ + UINT32 bufLen; + char *buf=NULL; + char path[1024]={0}; + struct stat statbuf; + int rc, fd; + BcmRet ret; + + bcmuLog_debug("reading block %d through %d", start_block, start_block+num_blocks); + + if (start_block != 0) + { + bcmuLog_error("cannot handle non-zero start block yet."); + return NULL; + } + + if (num_blocks > FAKE_NUM_PSP_FLASH_BLOCKS) + { + bcmuLog_error("requested more blocks than PSP flash blocks, not handled."); + return NULL; + } + + + /* first allocate the buffer we will need for the read */ + bufLen = FAKE_FLASH_BLOCK_SIZE * FAKE_NUM_PSP_FLASH_BLOCKS; + if ((buf = malloc(bufLen)) == NULL) + { + bcmuLog_error("malloc of %d bytes failed", bufLen); + return NULL; + } + memset(buf, 0x0, sizeof(bufLen)); + + /* form path to the flash file */ + if ((ret = bcmUtl_getBaseDir(path, sizeof(path))) != BCMRET_SUCCESS) + { + bcmuLog_error("getBaseDir failed, abort func"); + free(buf); + return NULL; + } + else + { + UINT32 offset; + + offset = strlen(path); + snprintf(&(path[offset]), sizeof(path)-offset, "/%s", FAKE_FLASH_PSP_FILENAME); + } + + + bcmuLog_debug("checking for flash file at %s", path); + if ((rc = stat(path, &statbuf)) < 0) + { + bcmuLog_debug("creating fake flash file and initialize to zeros"); + fd = open(path, O_CREAT|O_RDWR, 0644); + if (fd < 0) + { + bcmuLog_error("create of flash file %s failed, errno=%d", path, errno); + free(buf); + return NULL; + } + + /* fill rest of file with zeros */ + rc = write(fd, buf, bufLen); + bcmuLog_debug("filler write returned %d", rc); + + close(fd); + } + + + /* + * at this point, we know there is a flash file, so just open it and read it. + * Don't bother with offsets for now. Just assume PSP is at the beginning + * of the flash. + */ + fd = open(path, O_RDWR); + rc = read(fd, buf, num_blocks * FAKE_FLASH_BLOCK_SIZE); + if (rc != num_blocks * FAKE_FLASH_BLOCK_SIZE) + { + bcmuLog_error("unexpected rc %d from read, expected %d", + rc, num_blocks * FAKE_FLASH_BLOCK_SIZE); + free(buf); + buf = NULL; + } + + close(fd); + + return buf; +} + + +/** Write contents of pBuf to flash starting at start_block for total_blocks. + * + * @return 0 on success, -1 on failure. + */ +int fake_setSharedBlks(int start_block, int total_blocks, char *pBuf) +{ + int fd, rc; + int sts=-1; + char path[1024]={0}; + BcmRet ret; + + + bcmuLog_debug("setting block %d through %d, buf %p", start_block, start_block+total_blocks, pBuf); + + if (start_block != 0) + { + bcmuLog_error("cannot handle non-zero start block yet."); + return sts; + } + + if (total_blocks > FAKE_NUM_PSP_FLASH_BLOCKS) + { + bcmuLog_error("requested more blocks than PSP flash blocks, not handled."); + return sts; + } + + /* form path to the flash file */ + if ((ret = bcmUtl_getBaseDir(path, sizeof(path))) != BCMRET_SUCCESS) + { + bcmuLog_error("getBaseDir failed, abort func"); + return sts; + } + else + { + UINT32 offset; + + offset = strlen(path); + snprintf(&(path[offset]), sizeof(path)-offset, "/%s", FAKE_FLASH_PSP_FILENAME); + } + + bcmuLog_debug("opening fake flash file at %s", path); + if ((fd = open(path, O_RDWR)) < 0) + { + bcmuLog_error("Could not open %s", path); + return sts; + } + + rc = write(fd, pBuf, total_blocks * FAKE_FLASH_BLOCK_SIZE); + if (rc != total_blocks * FAKE_FLASH_BLOCK_SIZE) + { + bcmuLog_error("bad write, got %d expected %d", rc, total_blocks * FAKE_FLASH_BLOCK_SIZE); + } + else + { + bcmuLog_debug("%d blocks (%d bytes) written", total_blocks, total_blocks * FAKE_FLASH_BLOCK_SIZE); + sts = 0; + } + + close(fd); + + return sts; +} + + +/** Free resources used by previous flash read. + * + */ +void fake_retriedKfree(char *pShareBuf) +{ + free(pShareBuf); + + return; +} + + +SINT32 fake_flashRead(const char *filename, UINT8 *buf, UINT32 bufLen) +{ + char basedir[1024]={0}; + SINT32 rc, basedirLen; + UINT32 localBufLen = bufLen; + BcmRet ret; + + if ((ret = bcmUtl_getBaseDir(basedir, sizeof(basedir))) != BCMRET_SUCCESS) + { + bcmuLog_error("getBasedir failed, ret=%d", ret); + return ret; + } + + basedirLen = strlen(basedir); + rc = snprintf(&(basedir[basedirLen]), sizeof(basedir) - basedirLen, "/%s", filename); + if (rc >= ((SINT32) sizeof(basedir)) - basedirLen) + { + bcmuLog_error("basedir var not long enough to hold entire path"); + return BCMRET_RESOURCE_EXCEEDED; + } + + if (sysUtil_isFilePresent(basedir)) + { + // localBufLen is not used. + ret = sysUtil_copyToBuffer(basedir, buf, &localBufLen); + } + else + { + /* + * If the file does not exist, just return length 0. + */ + ret = 0; + } + + return ret; +} + + +SINT32 fake_flashWrite(const char *filename, UINT8 *buf, UINT32 bufLen) +{ + char basedir[1024]={0}; + SINT32 fd, rc, basedirLen; + BcmRet ret; + + if ((ret = bcmUtl_getBaseDir(basedir, sizeof(basedir))) != BCMRET_SUCCESS) + { + bcmuLog_error("getBasedir failed, ret=%d", ret); + return ret; + } + + basedirLen = strlen(basedir); + rc = snprintf(&(basedir[basedirLen]), sizeof(basedir) - basedirLen, "/%s", filename); + if (rc >= ((SINT32) sizeof(basedir)) - basedirLen) + { + bcmuLog_error("basedir var not long enough to hold entire path"); + return BCMRET_RESOURCE_EXCEEDED; + } + + fd = open(basedir, O_RDWR|O_CREAT|O_TRUNC, 0666); + if (fd < 0) + { + bcmuLog_error("Could not open %s, errno=%d", basedir, errno); + return BCMRET_INTERNAL_ERROR; + } + + rc = write(fd, buf, bufLen); + if (rc != (SINT32) bufLen) + { + bcmuLog_error("write failed, expected %u got %d", bufLen, rc); + ret = BCMRET_INTERNAL_ERROR; + } + else + { + bcmuLog_debug("wrote buf len=%u to %s", bufLen, basedir); + ret = BCMRET_SUCCESS; + } + + close(fd); + + return ret; +} + +SINT32 fake_kerSysBcmImageSetWhole(UINT8 *buf, SINT32 bufLen) +{ + return (fake_flashWrite("whole_flash.image", buf, bufLen)); +} + +SINT32 fake_kerSysBcmImageSetCfe(UINT8 *buf, SINT32 bufLen) +{ + return (fake_flashWrite("cfe.image", buf, bufLen)); +} + +SINT32 fake_flashFsKernelImage(UINT8 *buf, SINT32 bufLen) +{ + return (fake_flashWrite("fs_kernel.image", buf, bufLen)); +} + +SINT32 fake_kerSysPersistentSet(UINT8 *buf, UINT32 bufLen) +{ + return (fake_flashWrite("mdm.config", buf, bufLen)); +} + +SINT32 fake_kerSysBackupPsiSet(UINT8 *buf, UINT32 bufLen) +{ + return (fake_flashWrite("mdm-backup.config", buf, bufLen)); +} + +SINT32 fake_kerSysPersistentGet(UINT8 *buf, UINT32 bufLen) +{ + return (fake_flashRead("mdm.config", buf, bufLen)); +} + +SINT32 fake_kerSysBackupPsiGet(UINT8 *buf, UINT32 bufLen) +{ + return (fake_flashRead("mdm-backup.config", buf, bufLen)); +} + + +#endif /* DESKTOP_LINUX */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/prebuilt/libbcm_boardctl.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/prebuilt/libbcm_boardctl.so new file mode 100755 index 00000000000..1f85794df73 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boardctl/prebuilt/libbcm_boardctl.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/Bcmbuild.mk new file mode 100644 index 00000000000..de4be7f141e --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/Bcmbuild.mk @@ -0,0 +1,44 @@ +EXE := bcm_boot_launcher + +default: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(subst /userspace, /userspace,$(CURR_DIR)) +BUILD_DIR:=$(word 1, $(BUILD_DIR)) +include $(BUILD_DIR)/make.common + +ARCH=$(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/bin +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(BCM_FSBUILD_DIR)/public/include +ALLOWED_LIB_DIRS := /lib:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin + +all install: clean_legacy + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + + +clean: clean_legacy + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with dual makefiles.) +clean_legacy: + rm -f *.o *.d $(EXE) + + +shell: + bash -i diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/Makefile new file mode 100644 index 00000000000..8034bbe4c36 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/Makefile @@ -0,0 +1,13 @@ + +EXE = bcm_boot_launcher + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/autodetect new file mode 100644 index 00000000000..b546f961464 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/autodetect @@ -0,0 +1 @@ +dependson: public/libs/bcm_util diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/bcm_boot_launcher.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/bcm_boot_launcher.c new file mode 100644 index 00000000000..219bb1a93c7 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/bcm_boot_launcher.c @@ -0,0 +1,284 @@ +/*********************************************************************** + * + * <:copyright-BRCM:2011:DUAL/GPL:standard + * + * Copyright (c) 2011 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "bcm_ulog.h" + +struct element +{ + struct element *next; + struct element *prev; + char *filename; +}; + + +int start=0; +int stop=0; +char *dir = "/rom/etc/rc3.d"; +struct element *list_head=NULL; +static int build_list(void); +static int insert_element(const char *filename); +static void run_list(void); +static void free_list(void); + + +static void usage(void) +{ + printf("usage: bcm_boot_launcher [-v] [-d dir] start|stop\n"); + printf(" by default, start mode on %s\n", dir); + exit(-1); +} + +int main(int argc, char **argv) +{ + int c; + int rc; + + while ((c = getopt(argc, argv, "vspd:")) != -1) + { + switch(c) { + case 'v': + bcmuLog_setLevel(BCMULOG_LEVEL_DEBUG); + break; + + case 'd': + dir = optarg; + break; + + default: + usage(); + } + } + + if (optind+1 != argc) + { + usage(); + } + + if (!strcmp(argv[optind], "start")) + { + start = 1; + } + else if (!strcmp(argv[optind], "stop")) + { + stop = 1; + } + else + { + usage(); + } + + if (start) + { + bcmuLog_debug("start mode on dir=%s", dir); + } + else + { + bcmuLog_debug("stop mode on dir=%s", dir); + } + + rc = build_list(); + if (rc < 0) + { + bcmuLog_error("could not build list of scripts, aborting startup"); + free_list(); + exit(-1); + } + + run_list(); + + free_list(); + + exit(0); +} + + +/** build a doubly linked list of the scripts that we should execute in + * lexicographical order. + * + * @return 0 on success. + */ +int build_list() +{ + DIR *d; + struct dirent *dent; + int rc=0; + + if (NULL == (d = opendir(dir))) + { + bcmuLog_error("could not open %s, errno=%d", dir, errno); + return -1; + } + + while (NULL != (dent = readdir(d))) + { + if ((start && dent->d_name[0] == 'S') || + (stop && dent->d_name[0] == 'K')) + { + rc = insert_element(dent->d_name); + if (rc < 0) + break; + } + } + + closedir(d); + + return rc; + +#ifdef unittest + insert_element("S30apps"); + insert_element("S10drivers"); + insert_element("S05init"); + insert_element("S70smd"); + insert_element("S40custom"); + insert_element("S80final"); + return 0; +#endif +} + +int insert_element(const char *filename) +{ + struct element *ele; + struct element *curr; + + if (NULL == (ele = malloc(sizeof(struct element)))) + { + return -1; + } + + if (NULL == (ele->filename = malloc(strlen(filename)+1))) + { + free(ele); + return -1; + } + + strcpy(ele->filename, filename); + ele->next = NULL; + ele->prev = NULL; + + /* insert */ + if (list_head == NULL) + { + list_head = ele; + ele->next = ele; + ele->prev = ele; + return 0; + } + + curr = list_head; + do { + if (strcmp(ele->filename, curr->filename) < 0) + { + if (list_head == curr) + { + list_head = ele; + } + ele->next = curr; + ele->prev = curr->prev; + curr->prev->next = ele; + curr->prev = ele; + return 0; + } + curr = curr->next; + } while (curr != list_head); + + + /* went through the whole list without insertion, insert at end */ + ele->next = list_head; + ele->prev = list_head->prev; + list_head->prev->next = ele; + list_head->prev = ele; + + return 0; +} + + +void run_list() +{ + struct element *curr; + char cmdline[1024]={0}; + int rc; + + if (NULL == list_head) + { + return; + } + + curr = list_head; + do { + char *action=NULL; + if (start) + { + snprintf(cmdline, sizeof(cmdline)-1, "%s/%s start", dir, curr->filename); + action = "starting"; + } + else + { + snprintf(cmdline, sizeof(cmdline)-1, "%s/%s stop", dir, curr->filename); + action = "stopping"; + } + + bcmuLog_debug("%s: %s", action, cmdline); + if (0 != (rc = system(cmdline))) + { + bcmuLog_error("%s: %s returned %d", action, cmdline, rc); + } + + curr = curr->next; + } while (curr != list_head); +} + + +void free_list() +{ + struct element *curr; + struct element *tmp; + + if (NULL == list_head) + { + return; + } + + list_head->prev->next = NULL; + curr = list_head; + while (curr != NULL) + { + free(curr->filename); + tmp = curr->next; + free(curr); + curr = tmp; + } +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/prebuilt/bcm_boot_launcher b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/prebuilt/bcm_boot_launcher new file mode 100755 index 00000000000..b42cedc44a4 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_boot_launcher/prebuilt/bcm_boot_launcher differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/Makefile new file mode 100644 index 00000000000..730ae109884 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/Makefile @@ -0,0 +1,13 @@ + +EXE = bcm_bootstate + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/autodetect new file mode 100755 index 00000000000..ef2471abde4 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/autodetect @@ -0,0 +1,2 @@ +dependson: public/libs/bcm_util public/libs/sys_util public/libs/gen_util public/libs/bcm_flashutil public/libs/bcm_boardctl + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/bcm_bootstate.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/bcm_bootstate.c new file mode 100755 index 00000000000..27b07fa14b2 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/bcm_bootstate.c @@ -0,0 +1,185 @@ + +#include "bcm_flashutil.h" +#include "bcm_hwdefs.h" +#include +#include +#include + + +static char identBuf[1024]; +static const char *myGetIdent(int partition) +{ + int start = 0, end = 50; + + memset(identBuf, 0, sizeof(identBuf)); + bcmFlash_getIdent(partition, &start, &end, "imageversion", + identBuf, sizeof(identBuf)-1); + return identBuf; +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + char result, string1[] = "n/a", string2[] = "n/a"; + int higher = 1; + int boot = getBootPartition(); + int reboot; + int seq1 = -1; + int seq2 = -1; + + seq1 = getSequenceNumber(1); + seq2 = getSequenceNumber(2); + + if (seq1 > seq2) + higher = 1; + else + higher = 2; + + if ((seq1 == 0) && (seq2 == 999)) + higher = 1; + else if ((seq2 == 0) && (seq1 == 999)) + higher = 2; + + result = 0; + commit(1, &result); + if (result) + { + string1[0] = result; + string1[1] = '\0'; + } + + result = 0; + commit(2, &result); + if (result) + { + string2[0] = result; + string2[1] = '\0'; + } + + printf("\n Boot image state: "); + + switch(getBootImageState()) + { + case(BOOT_SET_NEW_IMAGE): + printf("BOOT_SET_NEW_IMAGE"); + reboot = higher; + break; + + case(BOOT_SET_OLD_IMAGE): + printf("BOOT_SET_OLD_IMAGE"); + reboot = (higher == 1) ? 2 : 1; + break; + + case(BOOT_SET_NEW_IMAGE_ONCE): + printf("BOOT_SET_NEW_IMAGE_ONCE"); + reboot = higher; + break; + + case(BOOT_SET_OLD_IMAGE_ONCE): + printf("BOOT_SET_OLD_IMAGE_ONCE"); + reboot = (higher == 1) ? 2 : 1; + break; + + case(BOOT_SET_PART1_IMAGE): + printf("BOOT_SET_PART1_IMAGE"); + reboot = 1; + break; + + case(BOOT_SET_PART1_IMAGE_ONCE): + printf("BOOT_SET_PART1_IMAGE_ONCE"); + reboot = 1; + break; + + case(BOOT_SET_PART2_IMAGE): + printf("BOOT_SET_PART2_IMAGE"); + reboot = 2; + break; + + case(BOOT_SET_PART2_IMAGE_ONCE): + printf("BOOT_SET_PART2_IMAGE_ONCE"); + reboot = 2; + break; + + default: + printf("UNKNOWN (boot latest image)"); + if (seq1 > seq2) + reboot = 1; + else + reboot = 2; + break; + } + + printf("\n Booted Partition: %s\n", (boot == 1) ? "First" : "Second"); + printf( " Reboot Partition: %s\n\n", (reboot == 1) ? "First" : "Second"); + + printf("%c%cFirst partition type : %s\n", (boot == 1) ? 'B' : ' ', (reboot == 1) ? '>' : ' ', (seq1 >= 0) ? ((string1[0] == 'n') ? "JFFS2/UBI" : "pureUBI/GPT") : "NONE"); + printf("%c%cFirst partition sequence number: %d\n", (boot == 1) ? 'B' : ' ', (reboot == 1) ? '>' : ' ', seq1); + printf("%c%cFirst partition image tag : %s\n", (boot == 1) ? 'B' : ' ', (reboot == 1) ? '>' : ' ', myGetIdent(1)); + + printf("%c%cFirst partition commit flag : %s\n", (boot == 1) ? 'B' : ' ', (reboot == 1) ? '>' : ' ', string1); + + printf("%c%cSecond partition type : %s\n", (boot == 2) ? 'B' : ' ', (reboot == 2) ? '>' : ' ', (seq2 >= 0) ? ((string2[0] == 'n') ? "JFFS2/UBI" : "pureUBI/GPT") : "NONE"); + printf("%c%cSecond partition sequence number: %d\n", (boot == 2) ? 'B' : ' ', (reboot == 2) ? '>' : ' ', seq2); + printf("%c%cSecond partition image tag : %s\n", (boot == 2) ? 'B' : ' ', (reboot == 2) ? '>' : ' ', myGetIdent(2)); + + printf("%c%cSecond partition commit flag : %s\n", (boot == 2) ? 'B' : ' ', (reboot == 2) ? '>' : ' ', string2); + + printf("\nTo set boot state usage: %s [state], where your state options are:\n", argv[0]); + + printf(" 1 or BOOT_SET_NEW_IMAGE\n"); + printf(" 2 or BOOT_SET_OLD_IMAGE\n"); + printf(" 3 or BOOT_SET_NEW_IMAGE_ONCE\n"); + printf(" 4 or BOOT_SET_OLD_IMAGE_ONCE\n"); + printf(" 5 or BOOT_SET_PART1_IMAGE\n"); + printf(" 6 or BOOT_SET_PART1_IMAGE_ONCE\n"); + printf(" 7 or BOOT_SET_PART2_IMAGE\n"); + printf(" 8 or BOOT_SET_PART2_IMAGE_ONCE\n"); + printf(" -------- test options --------\n"); + printf(" +1 ------ commit partition 1\n"); + printf(" -1 ------ uncommit partition 1\n"); + printf(" +2 ------ commit partition 2\n"); + printf(" -2 ------ uncommit partition 2\n"); + + return 0; + } + + if (!strcmp(argv[1], "1") || !strcmp(argv[1], "BOOT_SET_NEW_IMAGE")) + return(setBootImageState(BOOT_SET_NEW_IMAGE)); + + if (!strcmp(argv[1], "2") || !strcmp(argv[1], "BOOT_SET_OLD_IMAGE")) + return(setBootImageState(BOOT_SET_OLD_IMAGE)); + + if (!strcmp(argv[1], "3") || !strcmp(argv[1], "BOOT_SET_NEW_IMAGE_ONCE")) + return(setBootImageState(BOOT_SET_NEW_IMAGE_ONCE)); + + if (!strcmp(argv[1], "4") || !strcmp(argv[1], "BOOT_SET_OLD_IMAGE_ONCE")) + return(setBootImageState(BOOT_SET_OLD_IMAGE_ONCE)); + + if (!strcmp(argv[1], "5") || !strcmp(argv[1], "BOOT_SET_PART1_IMAGE")) + return(setBootImageState(BOOT_SET_PART1_IMAGE)); + + if (!strcmp(argv[1], "6") || !strcmp(argv[1], "BOOT_SET_PART1_IMAGE_ONCE")) + return(setBootImageState(BOOT_SET_PART1_IMAGE_ONCE)); + + if (!strcmp(argv[1], "7") || !strcmp(argv[1], "BOOT_SET_PART2_IMAGE")) + return(setBootImageState(BOOT_SET_PART2_IMAGE)); + + if (!strcmp(argv[1], "8") || !strcmp(argv[1], "BOOT_SET_PART2_IMAGE_ONCE")) + return(setBootImageState(BOOT_SET_PART2_IMAGE_ONCE)); + + if(strlen(argv[1]) == 2) + { + char commit_ops = argv[1][0]; + char partition = argv[1][1] - '0'; + + if( commit_ops == '+' || commit_ops == '-' ) + if( partition && (partition <= 2) ) + return(commit(partition,(commit_ops == '+' ? "1":"0"))); + } + + fprintf(stderr, "%s is an unknown boot state to set\n", argv[1]); + return -1; +} + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/prebuilt/bcm_bootstate b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/prebuilt/bcm_bootstate new file mode 100755 index 00000000000..6da6000080b Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_bootstate/prebuilt/bcm_bootstate differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/Makefile new file mode 100644 index 00000000000..2acd961f9f3 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/Makefile @@ -0,0 +1,13 @@ + +EXE = bcm_flasher + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/autodetect new file mode 100755 index 00000000000..27e5bc2987f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/autodetect @@ -0,0 +1,2 @@ +dependson: public/libs/bcm_flashutil public/libs/bcm_boardctl public/libs/bcm_util public/libs/sys_util public/libs/gen_util + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/bcm_flasher.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/bcm_flasher.c new file mode 100755 index 00000000000..978bc5bda1d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/bcm_flasher.c @@ -0,0 +1,172 @@ + +#include +#include "bcm_imgif.h" +#include "cms_image.h" +#include +#include + +#ifdef RTCONFIG_URLFW +#include "bcm_flashutil.h" +#include + +extern FILE *url_fopen(const char *path, const char *mode); + +#define BOOT_SET_NEW_IMAGE '0' + +#endif + +CmsImageFormat parseImgHdr(UINT8 *bufP __attribute__((unused)), UINT32 bufLen __attribute__((unused))) +{ + int result = CMS_IMAGE_FORMAT_FLASH; + + return result; +} + +#define BCM_FLASHER_STD_BUFFSIZE 1024 + +int main(int argc, char *argv[]) +{ + unsigned char * buffer; + int buffer_size = BCM_FLASHER_STD_BUFFSIZE; + unsigned int size, amount; + FILE *fp; + imgif_flash_info_t flash_info; + static IMGIF_HANDLE imgifHandle = NULL; + int reboot_new = 0; + int urlfw = 0; +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + imgif_img_info_t img_info; + unsigned int force_upd_img_idx =0; + + /* Usage brcm_flasher */ + if (argc >= 4) { + reboot_new = atoi(argv[3]); + } else if (argc >= 3) { + force_upd_img_idx = atoi(argv[2]); + fprintf(stderr, "bcm_flasher argc %d argv %s \n", argc, argv[2]); + if (force_upd_img_idx !=1 && force_upd_img_idx != 2) + force_upd_img_idx = 0; + } else if (argc != 2) { + fprintf(stderr, "Flash image burner, usage: %s [filename of image to burn] \n", argv[0]); + return 0; + } + + fprintf(stderr, "Flash image burner, %s idx %d reboot_new %d, argc %d\n", argv[0], force_upd_img_idx, reboot_new, argc); +#else + if (argc >= 3) { + reboot_new = atoi(argv[2]); + } else if (argc != 2) + { + fprintf(stderr, "Flash image burner, usage: %s [filename of image to burn]\n", argv[0]); + return 0; + } + fprintf(stderr, "Flash image burner, %s, reboot_new %d\n", argv[0], reboot_new); +#endif + +#ifdef RTCONFIG_URLFW + urlfw = 1; + if ( (fp = url_fopen(argv[1], "r")) == 0) +#else + urlfw = 0; + if ( (fp = fopen(argv[1], "r")) == 0) +#endif + { + fprintf(stderr, "error!!! Could not %sopen %s\n", urlfw?"url-":"", argv[1]); + return -1; + } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + rewind(fp); + + printf("File size 0x%x (%d)\n", size, size); + + imgifHandle = imgif_open(parseImgHdr, NULL); + + if (imgifHandle == NULL) + { + fprintf(stderr, "ERROR!!! imgif_open() failed\n"); + fclose(fp); + return -1; + } + + if (imgif_get_flash_info(&flash_info) != 0) + { + fprintf(stderr, "ERROR!!! imgif_get_flash_info() failed\n"); + imgif_close(imgifHandle, 1); + fclose(fp); + return -1; + } +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + memset(&img_info, 0, sizeof(img_info)); + if (force_upd_img_idx) { + img_info.force_upd_img_idx = force_upd_img_idx; + imgif_set_image_info(imgifHandle, &img_info); + } + #endif + + printf("Flash type 0x%x, flash size 0x%x, block size 0x%x\n", flash_info.flashType, flash_info.flashSize, flash_info.eraseSize); + + /* If we have a valid erase size, use it for allocating our buffer */ + if ( flash_info.eraseSize ) + buffer_size = flash_info.eraseSize; + + if ( (buffer = malloc(buffer_size)) == 0) + { + fprintf(stderr, "ERROR!!! Could not allocate memory for file %s\n", argv[1]); + imgif_close(imgifHandle, 1); + fclose(fp); + return -1; + } + + while (size) + { + amount = (size > (unsigned int)buffer_size) ? (unsigned int)buffer_size : size; + + if (fread (buffer, 1, amount, fp) != amount) + { + fprintf(stderr, "ERROR!!! Could not read image from file %s\n", argv[1]); + free(buffer); + imgif_close(imgifHandle, 1); + fclose(fp); + return -1; + } + + if (amount != (unsigned int)imgif_write(imgifHandle, buffer, amount)) + { + fprintf(stderr, "ERROR!!! Failed to process %d bytes. Not flashing upgrade image!\n", amount); + free(buffer); + imgif_close(imgifHandle, 1); + fclose(fp); + return -1; + } + + printf("."); + + size -= amount; + } + + free(buffer); + fclose(fp); + + if (imgif_close(imgifHandle, 0) != 0) + { + fprintf(stderr, "ERROR!!! Failed to flash upgrade image \n"); + return -1; + } + else + printf("\nImage flash complete, you may reboot the board\n"); + +#ifdef RTCONFIG_URLFW + if(reboot_new) + { + setBootImageState(BOOT_SET_NEW_IMAGE); + sleep(1); + fprintf(stderr, "ready to reboot for new img..\n"); + reboot(RB_AUTOBOOT); + } +#endif + + return size; // return the amount we copied +} + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/mtd_curl.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/mtd_curl.c new file mode 100644 index 00000000000..0ca3cc5ff05 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/mtd_curl.c @@ -0,0 +1,346 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2020, ASUSTeK Inc. + * Based on fbida code by Gerd Hoffmann. + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#ifdef RTCONFIG_URLFW + +#include +#include + +struct url_state { + CURLM *multi; + CURL *curl; + size_t pos; + struct { + size_t pos; + size_t len; + size_t size; + unsigned char *data; + } buf; + struct { + size_t pos; + int running:1; + int body:1; + int eof:1; + } stream; + char *path; +}; + +/* not necessary for single applet +static void __attribute__((constructor)) curl_init(void) +{ + curl_global_init(CURL_GLOBAL_ALL); +} + +static void __attribute__((destructor)) curl_fini(void) +{ + curl_global_cleanup(); +} +*/ + +static size_t curl_header(void *data, size_t size, size_t nmemb, void *handle) +{ + struct url_state *h = handle; + + h->stream.running = 1; + size *= nmemb; + + return size; +} + +static size_t curl_write(void *data, size_t size, size_t nmemb, void *handle) +{ + struct url_state *h = handle; + + h->stream.running = h->stream.body = 1; + size *= nmemb; + + if (h->buf.size < size) { + void *buf = realloc(h->buf.data, size); + if (buf) { + h->buf.data = buf; + h->buf.size = size; + } else + size = h->buf.size; + } + + h->buf.pos = h->stream.pos; + h->buf.len = size; + memcpy(h->buf.data, data, size); + + h->stream.pos += size; + return size; +} + +static int curl_setup(struct url_state *h, int *running) +{ + CURLMcode rc; + char *url; + + if (h->curl == NULL) { + h->curl = curl_easy_init(); + if (h->curl == NULL) + return -1; + url = h->path; + } else { + curl_multi_remove_handle(h->multi, h->curl); + if (curl_easy_getinfo(h->curl, CURLINFO_EFFECTIVE_URL, &url) == CURLE_OK && + url != NULL && strcmp(url, h->path) != 0) { + free(h->path); + h->path = strdup(url); + if (h->path == NULL) + goto error; + } + curl_easy_reset(h->curl); + } + + curl_easy_setopt(h->curl, CURLOPT_URL, h->path); + curl_easy_setopt(h->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(h->curl, CURLOPT_FAILONERROR, 1L); + + curl_easy_setopt(h->curl, CURLOPT_WRITEFUNCTION, curl_write); + curl_easy_setopt(h->curl, CURLOPT_WRITEDATA, h); + curl_easy_setopt(h->curl, CURLOPT_HEADERFUNCTION, curl_header); + curl_easy_setopt(h->curl, CURLOPT_HEADERDATA, h); + curl_easy_setopt(h->curl, CURLOPT_HEADER, 0L); + + //curl_easy_setopt(h->curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(h->curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(h->curl, CURLOPT_NOSIGNAL, 1L); + + curl_easy_setopt(h->curl, CURLOPT_CONNECTTIMEOUT, 10L); + //curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120L); + + memset(&h->stream, 0, sizeof(h->stream)); + + if (curl_multi_add_handle(h->multi, h->curl) != CURLM_OK) + goto error; + + while ((rc = curl_multi_perform(h->multi, running)) == CURLM_CALL_MULTI_PERFORM); + if (rc != CURLM_OK) { + curl_multi_remove_handle(h->multi, h->curl); + goto error; + } + + return 0; + +error: + curl_easy_cleanup(h->curl); + h->curl = NULL; + return -1; +} + +static int curl_transfer(struct url_state *h) +{ + CURLMcode rc; + int running; + + rc = curl_multi_wait(h->multi, NULL, 0, 1000000, NULL); + if (rc != CURLM_OK) + return -1; + + while ((rc = curl_multi_perform(h->multi, &running)) == CURLM_CALL_MULTI_PERFORM); + if (rc != CURLM_OK) + return -1; + + if (running == 0) + h->stream.eof = 1; + + return 0; +} + +static ssize_t url_read(void *handle, char *buf, size_t size) +{ + struct url_state *h = handle; + size_t bytes, total; + int running; + + for (total = 0; size > 0;) { + if (h->pos >= h->buf.pos && h->pos < h->buf.pos + h->buf.len) { + bytes = h->buf.pos + h->buf.len - h->pos; + if (bytes > size) + bytes = size; + memcpy(buf + total, h->buf.data + h->pos - h->buf.pos, bytes); + size -= bytes; + total += bytes; + h->pos += bytes; + continue; + } + if (h->pos < h->buf.pos) { + h->buf.pos = h->buf.len = 0; + if (curl_setup(h, &running) < 0) + return -1; + } + if (h->stream.eof) + break; + if (curl_transfer(h) < 0) { + if (total == 0) + return -1; + break; + } + } + + return total; +} + +static int url_seek(void *handle, off64_t *pos, int whence) +{ + struct url_state *h = handle; + CURLMcode rc; + curl_off_t size; + off64_t new = *pos; + + switch (whence) { + case SEEK_SET: + break; + case SEEK_CUR: + new += h->pos; + break; + case SEEK_END: + rc = curl_easy_getinfo(h->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &size); + if (rc != CURLM_OK || size == -1) { + errno = EINVAL; + return -1; + } + new += size; + break; + } + *pos = h->pos = new; + + return 0; +} + +static int url_close(void *handle) +{ + struct url_state *h = handle; + + if (h->multi && h->curl) + curl_multi_remove_handle(h->multi, h->curl); + if (h->multi) + curl_multi_cleanup(h->multi); + if (h->curl) + curl_easy_cleanup(h->curl); + free(h->buf.data); + free(h->path); + free(h); + + return 0; +} + +static cookie_io_functions_t url_hooks = { + .read = url_read, + .seek = url_seek, + .close = url_close, +}; + +static int url_scheme(const char *path) +{ + static const char * const protocols[] = { +#ifdef RTCONFIG_HTTPS + "https://", +#endif + "http://", + "ftp://", + NULL, + }; + const char * const *p; + + for (p = protocols; *p != NULL; p++) { + if (strncasecmp(path, *p, strlen(*p)) == 0) + return 1; + } + + return 0; +} + +FILE *url_fopen(const char *path, const char *mode) +{ + struct url_state *h; + FILE *fp; + int running, err = 0; + + if (!url_scheme(path)) + return fopen(path, mode); + + if (strchr(mode, 'w') != NULL) { + errno = EACCES; + return NULL; + } + + h = calloc(1, sizeof(*h)); + if (h == NULL) + return NULL; + + h->path = strdup(path); + if (h->path == NULL) { + err = errno; + goto error; + } + + h->multi = curl_multi_init(); + if (h->multi == NULL) { + err = errno; + goto error; + } + + if (curl_setup(h, &running) < 0) { + err = errno; + goto error; + } + + if (!running && !h->stream.running) { + err = ENOENT; + goto error; + } + + fp = fopencookie(h, mode, url_hooks); + if (fp == NULL) { + err = errno; + goto error; + } + + while (!h->stream.body && !h->stream.eof) { + if (curl_transfer(h) < 0) + break; + } + + return fp; + +error: + url_close(h); + errno = err; + return NULL; +} + +#endif /* RTCONFIG_URLFW */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/prebuilt/bcm_flasher b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/prebuilt/bcm_flasher new file mode 100755 index 00000000000..0ce32e8482b Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flasher/prebuilt/bcm_flasher differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/Bcmbuild.mk new file mode 100644 index 00000000000..aaa292e269e --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/Bcmbuild.mk @@ -0,0 +1,88 @@ +LIB := libbcm_flashutil.so + +default: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + +ARCH=$(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/include +ETC_INSTALL_DIR := $(BCM_FSBUILD_DIR)/etc +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(HEADER_INSTALL_DIR) \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/../flash \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(HND_SRC)/router-sysdep/fdt/dtc-1.5.1 + +CFLAGS += -DCHIP_FAMILY_ID_HEX=0x$(BRCM_CHIP) + +ifneq ($(strip $(BRCM_NO_AUTOCOMMIT_IMAGE)),) +CFLAGS += -DNO_AUTOCOMMIT_IMAGE +endif + +ifeq ($(strip $(CFE_DDR_TYPE_CHECK)),y) +CFLAGS += -DDDR_TYPE_CHECK +endif + +ifeq ($(strip $(DISABLE_NOR_RAW_PARTITION)),y) +CFLAGS += -DDISABLE_NOR_RAW_PARTITION +endif + +ifeq ($(strip $(DESKTOP_LINUX)),) +# Do not define this flag in DESKTOP_LINUX mode, code does not support it. +ifneq ($(strip $(BRCM_INCREMENTAL_IMAGE_LOAD)),) +CFLAGS += -DSUPPORT_INCREMENTAL_FLASHING +endif +endif + +ifneq ($(strip $(BUILD_NAND_UBIFS_SINGLE_IMAGE)),) +CFLAGS += -DCUSTOM_NAND_SINGLE_IMAGE=1 +endif + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR ETC_INSTALL_DIR \ + BRCM_NO_AUTOCOMMIT_IMAGE + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) +FINAL_ETC_INSTALL_DIR := $(INSTALL_DIR)/etc + + +all install: clean_legacy + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) +ifneq ($(strip $(BRCM_NO_AUTOCOMMIT_IMAGE)),) + @echo "INSTALLING COMMIT AFTER REBOOT SCRIPT (FINAL)" + mkdir -p $(FINAL_ETC_INSTALL_DIR)/init.d + mkdir -p $(FINAL_ETC_INSTALL_DIR)/rc3.d + install -p -m 0755 -t $(FINAL_ETC_INSTALL_DIR)/init.d $(ETC_INSTALL_DIR)/init.d/commit.sh + (cd $(FINAL_ETC_INSTALL_DIR)/rc3.d; rm -f S68commit; ln -s ../init.d/commit.sh S68commit) +endif + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + rm -f $(FINAL_ETC_INSTALL_DIR)/init.d/commit.sh + rm -f $(FINAL_ETC_INSTALL_DIR)/rc3.d/S68commit + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with dual makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + + +shell: + bash -i diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/Makefile new file mode 100644 index 00000000000..b3e6199a4a6 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/Makefile @@ -0,0 +1,13 @@ + +LIB = libbcm_flashutil.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil.c new file mode 100755 index 00000000000..a2bc9309516 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil.c @@ -0,0 +1,1991 @@ +/*********************************************************************** + * <:copyright-BRCM:2007:DUAL/GPL:standard + * + * Copyright (c) 2007 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +#include +#include +#include // types +#include +#include +#include // for open +#include +#include +#include +#include // close + +#include "board.h" /* in bcmdrivers/opensource/include/bcm963xx, for BCM_IMAGE_CFE */ +#include "bcm_boarddriverctl.h" +#include "bcm_ulog.h" +#include "sysutil_fs.h" + +#include "bcm_flashutil.h" +#include "bcm_flashutil_private.h" +#include "bcm_flashutil_nand.h" +#include "bcm_flashutil_emmc.h" +#include "bcm_flashutil_nor.h" +#include "flash_api.h" +#include +#include "os_defs.h" + + + +#define IS_ERR_OR_NULL(x) ((x)==0) +#define IS_ERR(x) ((x)<0) +#define IS_NULL(x) ((x)==0) + +#define ERROR -1 +#define SUCCESS 0 + +/* #define FLASHUTIL_DEBUG 1 */ +#if defined(FLASHUTIL_DEBUG) +#define flashutil_debug(fmt, arg...) \ + fprintf(stderr, "%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#else +#define flashutil_debug(fmt, arg...) +#endif +#define flashutil_print(fmt, arg...) \ + fprintf(stderr, "%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#define flashutil_error(fmt, arg...) \ + fprintf(stderr, "ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + + +/* + * gFlashInfo is the cached flash info variable. 0 means no value yet. + * non-zero means we already got the value and don't need to run low level + * functions anymore. + */ +static unsigned int gFlashInfo = 0; + +#ifndef DESKTOP_LINUX + +#define UPDATE_FLASH_INFO() if(gFlashInfo == 0) {getFlashInfo(&gFlashInfo);} + +#ifdef DISABLE_NOR_RAW_PARTITION +static int disable_nor_raw_partition = 1; +#else +static int disable_nor_raw_partition = 0; +#endif + +/* Prototypes */ +static unsigned int pkgtb_getCrc32(const unsigned char *pdata, unsigned int size, unsigned int crc_initial); +#endif /* DESKTOP_LINUX */ + + +/** Main entry point for board ioctl actions. See comments in + * bcm_boarddriverctl.h for detailed info about this function. + */ +BcmRet devCtl_boardIoctl(UINT32 boardIoctl, + BOARD_IOCTL_ACTION action, + char *string, + SINT32 strLen, + SINT32 offset, + void *data) +{ +#ifndef DESKTOP_LINUX + BcmRet ret=BCMRET_SUCCESS; + + UPDATE_FLASH_INFO(); + + if( (((boardIoctl == BOARD_IOCTL_FLASH_READ || boardIoctl == BOARD_IOCTL_FLASH_WRITE) && + ((action == SCRATCH_PAD) || (action == PERSISTENT) || (action == BACKUP_PSI) || (action == SYSLOG))) || + (boardIoctl == BOARD_IOCTL_FLASH_LIST)) && + ((gFlashInfo & FLASH_INFO_FLAG_NOR) == 0 || disable_nor_raw_partition == 1) + ) + { + ret = devCtl_flashConfigAccess(boardIoctl, action, string, strLen, offset, data); + return ret; + } +#endif + + return (devCtl_boardDriverIoctl(boardIoctl, action, + string, strLen, offset, data)); +} + +#ifndef DESKTOP_LINUX +void composeConfigFileName(UINT32 boardIoctl, BOARD_IOCTL_ACTION action, + const char *compName, char *fname, unsigned int len); + +BcmRet devCtl_flashConfigAccess(UINT32 boardIoctl, BOARD_IOCTL_ACTION action, + char *string, SINT32 strLen, + SINT32 offset, void *data) +{ + BcmRet ret = BCMRET_SUCCESS; + + if( action == SCRATCH_PAD ) + { + switch(boardIoctl) + { + case BOARD_IOCTL_FLASH_LIST: + ret = devCtl_scratchPadList(SCRATCH_PAD_FILE_NAME, data, offset); + break; + + case BOARD_IOCTL_FLASH_READ: + ret = devCtl_scratchPadGet(SCRATCH_PAD_FILE_NAME, string, data, offset); + break; + + case BOARD_IOCTL_FLASH_WRITE: + if( offset == -1 ) + ret = devCtl_scratchPadClearAll(SCRATCH_PAD_FILE_NAME); + else + ret = devCtl_scratchPadSet(SCRATCH_PAD_FILE_NAME, string, data, offset); + break; + default: + bcmuLog_error("unhandled BOARD_IOCTL code %d for scratch pad", boardIoctl); + ret = BCMRET_INVALID_ARGUMENTS; + break; + } + } + else + { + char fname[MAX_PSI_FILE_NAME_LEN]={0}; + + switch(action) + { + case PERSISTENT: + case BACKUP_PSI: + composeConfigFileName(boardIoctl, action, (char *)data, + fname, sizeof(fname)); + break; + + case SYSLOG: + snprintf(fname, sizeof(fname), "%s", SYSLOG_FILE_NAME); + break; + + default: + bcmuLog_error("unhandled action %d in BOARD_IOCTL code %d", + action, boardIoctl); + return BCMRET_INVALID_ARGUMENTS; + } + + if ( boardIoctl == BOARD_IOCTL_FLASH_READ ) + { + bcmuLog_notice("reading from fname %s", fname); + ret = devCtl_flashReadFile(fname, string, strLen); + } + else if( boardIoctl == BOARD_IOCTL_FLASH_WRITE ) + { + bcmuLog_notice("writing to fname %s (len=%d)", fname, strLen); + ret = devCtl_flashWriteFile(fname, string, strLen); + sync(); + } + else + { + bcmuLog_error("unhandled BOARD_IOCTL code %d", boardIoctl); + ret = BCMRET_INVALID_ARGUMENTS; + } + } + + return ret; +} + + +void composeConfigFileName(UINT32 boardIoctl, BOARD_IOCTL_ACTION action, + const char *compName, char *fname, unsigned int len) +{ + // Distributed MDM config files has _compName. + if (compName != NULL && compName[0] != '\0') + { + if (action == PERSISTENT) + snprintf(fname, len, "%s_%s", PSI_FILE_NAME, compName); + else + snprintf(fname, len, "%s_%s", PSI_BACKUP_FILE_NAME, compName); + } + else + { + if (action == PERSISTENT) + snprintf(fname, len, "%s", PSI_FILE_NAME); + else + snprintf(fname, len, "%s", PSI_BACKUP_FILE_NAME); + } + + if (boardIoctl == BOARD_IOCTL_FLASH_WRITE) + { + // There is no fallback for write operation. Write it to which ever + // file was specified. + return; + } + + if (sysUtil_isFilePresent(fname)) + { + return; + } + + // Distributed MDM filename does not exist, fallback to monolithic name + bcmuLog_notice("%s does not exist, fallback", fname); + if (action == PERSISTENT) + snprintf(fname, len, "%s", PSI_FILE_NAME); + else + snprintf(fname, len, "%s", PSI_BACKUP_FILE_NAME); + + return; +} + +#endif /* DESKTOP_LINUX */ + + +/** read the nvramData struct from the in-memory copy of nvram. + * The caller is not required to have flashImageMutex when calling this + * function. However, if the caller is doing a read-modify-write of + * the nvram data, then the caller must hold flashImageMutex. This function + * does not know what the caller is going to do with this data, so it + * cannot assert flashImageMutex held or not when this function is called. + * + * @return pointer to NVRAM_DATA buffer which the caller must free + * or NULL if there was an error + */ +int readNvramData(void *nvramData) +{ +#ifndef DESKTOP_LINUX + int ret = 0; + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = nandReadNvramData(nvramData); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = emmcReadNvramData(nvramData); + break; + + default: + break; + } + return ret; +#else + flashutil_print("readNvramData(%p)", nvramData); + return 1; +#endif +} + + +int getFlashInfo(unsigned int *flags) +{ + if (flags == NULL) + { + fprintf(stderr, "flags is NULL!"); + return ERROR; + } + + if (gFlashInfo != 0) + { + /* use cached result */ + *flags = gFlashInfo; + return SUCCESS; + } + + return (getFlashInfoUncached(flags)); +} + +int getFlashInfoUncached(unsigned int *flags) +{ + if (flags == NULL) + { + fprintf(stderr, "flags is NULL!"); + return ERROR; + } + else + { + *flags = 0; + } + +#ifndef DESKTOP_LINUX + { + /* First try NAND, and if not NAND, see if it is EMMC. + * TOOD: There seems to be a bug in libc where if you run several + * popens back to back, libc loses track of the fp and the fgets hangs. + * So in the emmc case, we would first run a popen in nandIsBootDevice, + * and then immediately run another popen in emmcIsBootDevice, so + * there might be a hang. If so, put a sleep(1) before the call to + * emmcIsBootDevice(). + */ + if( nandIsBootDevice() ) + { + *flags = FLASH_INFO_FLAG_NAND; + } + else if( emmcIsBootDevice() ) + { + *flags = FLASH_INFO_FLAG_EMMC; + } + else + { + /* If not NAND and not EMMC, default to NOR */ + *flags = FLASH_INFO_FLAG_NOR; + } + } +#else + *flags = FLASH_INFO_FLAG_NAND; +#endif + + /* cache the result */ + gFlashInfo = *flags; + + return SUCCESS; +} + +int getFlashTotalSize(unsigned int *size) +{ + unsigned int value = 0; + BcmRet ret = BCMRET_SUCCESS; + +#ifdef DESKTOP_LINUX + value = 512*1024*1024; // 512MB +#else + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = get_mtd_master_size(&value); + break; + case FLASH_INFO_FLAG_EMMC: + ret = emmcGetFlashSize(&value); + break; + case FLASH_INFO_FLAG_NOR: + default: + fprintf(stderr, "Not implemented yet.\n"); + break; + } +#endif + *size = value; + + return ret; +} + +unsigned int get_flash_type(void) +{ + unsigned int value = 0; + + devCtl_boardIoctl(BOARD_IOCTL_GET_FLASH_TYPE, 0, NULL, 0, 0, (void *)&value); + + return(value); +} + +unsigned int otp_is_btrm_boot(void) +{ + unsigned int value = 0; +#ifndef DESKTOP_LINUX + devCtl_boardIoctl(BOARD_IOCTL_GET_BTRM_BOOT, 0, NULL, 0, 0, (void *)&value); +#endif + return(value); +} + +unsigned int otp_is_boot_secure(void) +{ + unsigned int value = 0; +#ifndef DESKTOP_LINUX + devCtl_boardIoctl(BOARD_IOCTL_GET_BOOT_SECURE, 0, NULL, 0, 0, (void *)&value); +#endif + return(value); +} + +/* Only gen3 bootroms and later support a manufacturing secure stage (ie 4908, 6858, etc) */ +unsigned int otp_is_boot_mfg_secure(void) +{ + unsigned int value = 0; +#ifndef DESKTOP_LINUX + devCtl_boardIoctl(BOARD_IOCTL_GET_BOOT_MFG_SECURE, 0, NULL, 0, 0, (void *)&value); +#endif + return(value); +} + + +unsigned int get_chip_id(void) +{ + unsigned int chip_id = 0; +#ifndef DESKTOP_LINUX + devCtl_boardIoctl(BOARD_IOCTL_GET_CHIP_ID, 0, NULL, 0, 0, (void *)&chip_id); +#endif + return(chip_id); +} + + +#ifndef DESKTOP_LINUX +unsigned int getset_boot_inactive_image(int flag) +{ + unsigned int value = 0; + devCtl_boardIoctl(BOARD_IOCTL_GETSET_BOOT_INACTIVE_IMAGE, 0, NULL, 0, flag, (void *)&value); + return(value); +} +#else +unsigned int getset_boot_inactive_image(int flag __attribute__((unused))) +{ + return(0); +} +#endif + + +int devCtl_getSequenceNumber(int image) +{ + unsigned int flag=0; + + getFlashInfo(&flag); + if (flag & (FLASH_INFO_FLAG_NAND | FLASH_INFO_FLAG_EMMC)) // NAND flash, no need to dig into kernel space + return(getSequenceNumber(image)); + else + return( (int) devCtl_boardIoctl(BOARD_IOCTL_GET_SEQUENCE_NUMBER, 0, NULL, 0, image, NULL) ); +} + +int getSequenceNumber(int imageNumber) +{ /* NAND Flash */ +#ifndef DESKTOP_LINUX + int seqNumber = -1; + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + seqNumber = nandGetSequenceNumber(imageNumber); + break; + + case FLASH_INFO_FLAG_EMMC: + seqNumber = emmcGetSequenceNumber(imageNumber); + break; + + case FLASH_INFO_FLAG_NOR: + if( !isLegacyFlashLayout() ) + { + //FIXME: SPINOR flash only support single image. + seqNumber = imageNumber; + } + break; + + default: + break; + } +#else + int seqNumber = imageNumber; +#endif /* DESKTOP_LINUX */ + + return(seqNumber); +} + +int getNextSequenceNumber( int seqNumImg1, int seqNumImg2 ) +{ + int seq_num = -1; + + if( (seqNumImg1 == -1) && (seqNumImg2 == -1) ) + seq_num = 999; + else + seq_num = seqNumImg1 > seqNumImg2 ? seqNumImg1+1:seqNumImg2+1; + + /* Handle wrap-around case */ + if( seq_num > 999 ) + seq_num = 0; + + /* Handle zero case */ + if( (seq_num == seqNumImg1) || (seq_num == seqNumImg2) ) + seq_num++; + + return seq_num; +} + +//#define DUMP_VER_STR 1 +int devCtl_getImageVersion(int partition, char *verStr, int verStrSize) +{ + char tag[BUFLEN_256+1]={0}; + int status, i; + int start = -1; + int strSize = -1; + int end = -1; + int keyLen = strlen("$imageversion"); + + memset(tag, 0x0, sizeof(tag)); + status = bcmFlash_getIdent(partition, &start, &end, "imageversion", + tag, sizeof(tag)-1); + +#ifdef DUMP_VER_STR + printf("%s: Image version tag[%d]:\n", __FUNCTION__, status); + for(i=0; i< BUFLEN_256+1; i++) + { + printf("%c", tag[i]); + } + printf("\n"); +#endif + + if (status > keyLen) + { + for (i = keyLen; i<(BUFLEN_256+1) && i= verStrSize) ? + verStrSize : (status - i); +#ifdef DUMP_VER_STR + printf("%s: offset:%d, size:%d \n",__FUNCTION__, i, strSize); +#endif + + memcpy(verStr, &tag[i], strSize); + status = strSize; + } + else + { + status = -1; + fprintf(stderr, "\nImage version not found.\n"); + } + + return(status); + +} + +uint64_t getSysfsBytes(char * pathname) +{ + FILE *fp; + char line[256]={0}; + char *temp; + uint64_t bytes = 0; + + if( access( pathname, F_OK ) == 0 ) + { + fp = fopen(pathname,"r"); + if (fp == NULL) + { + printf("%s: Error! Could not open %s!\n", __FUNCTION__, pathname); + } + else + { + if ( fgets(line, sizeof(line), fp) ) + bytes = strtoull(line, &temp, 10); + else + printf("%s: Error reading sysfs entry %s!\n", __FUNCTION__, pathname); + + fclose(fp); + } + } + return bytes; +} + +#ifdef DESKTOP_LINUX + +int devCtl_getImageState(void) +{ + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, BOOT_GET_BOOT_IMAGE_STATE, NULL) ); +} + +int devCtl_getBootedImagePartition(void) +{ + return( (int) devCtl_boardDriverIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 1, BOOT_GET_BOOTED_IMAGE_ID, NULL) ); +} + +int getImageVersion(uint8_t *imagePtr __attribute__((unused)), int imageSize __attribute__((unused)), char *image_name, int image_name_len) +{ + // See also bcm_boardctl/linux/board.c BOOT_GET_IMAGE_VERSION + strncpy(image_name, "DESKTOPLINUX", image_name_len); + return 0; +} + +int setBootImageState(int newState) +{ + /* this will go to the fake boardioctl handler */ + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, newState, NULL) ); +} + +int devCtl_setImageState(int state) +{ + /* this will go to the fake boardioctl handler */ + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, state, NULL) ); +} + +int getBootImageState(void) +{ + /* this will go to the fake boardioctl handler */ + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, BOOT_GET_BOOT_IMAGE_STATE, NULL) ); +} + +int getBootedValue(void) +{ + /* this will go to the fake boardioctl handler */ + return( (int) devCtl_boardDriverIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 1, BOOT_GET_BOOTED_IMAGE_ID, + NULL) ); +} + +int verifyImageDDRType(uint32_t wfiFlags __attribute__((unused)), PNVRAM_DATA pNVRAM __attribute__((unused))) +{ + return 0; +} + +int getBootPartition( void ) +{ + return 1; +} + +int getUpgradePartition( void ) +{ + return 1; +} + +int commit( int partition __attribute__((unused)), char *string __attribute__((unused))) +{ + return 0; +} + +int bcmFlash_getIdent(int part __attribute__((unused)), int *start __attribute__((unused)), int *end __attribute__((unused)), const char * key __attribute__((unused)), char * line __attribute__((unused)), int len __attribute__((unused))) +{ + return 0; +} + +int isLegacyFlashLayout(void) +{ + return -1; +} + +int setImgSeqNum( int img_idx __attribute__((unused)), int seq __attribute__((unused))) +{ + return 0; +} + +int getImgSeqNum( int img_idx __attribute__((unused)), int * seq __attribute__((unused))) +{ + return 0; +} +#else /* end of DESKTOP_LINUX, start of real system code */ + +int verifyImageDDRType(uint32_t wfiFlags, PNVRAM_DATA pNVRAM) +{ +#if defined(DDR_TYPE_CHECK) + uint32_t brdtype, imgtype; + int rc = -1; + char* brdstr, *imgstr; + + if( pNVRAM ) { + brdtype = pNVRAM->ulMemoryConfig&BP_DDR_TYPE_MASK; + + imgtype = wfiFlags&WFI_FLAG_DDR_TYPE_MASK; + brdstr = (brdtype == BP_DDR_TYPE_DDR3) ? "DDR3" : "DDR4"; + + if( imgtype == WFI_FLAG_DDR_TYPE_NONE ) { + fprintf(stderr, "\nImage ddr type not set. Probably an old image that does not support DDR type flag.\n"); + fprintf(stderr, "If you are sure the image has same DDR type as the board DDR type %s, use CFE and force command to update.\n", brdstr); + rc = -1; + } else { + imgstr = (imgtype == WFI_FLAG_DDR_TYPE_DDR3) ? "DDR3" : "DDR4"; + if( imgstr[3] != brdstr[3] ) { + fprintf(stderr, "\nMismatch image ddr type %s board ddr type %s, flash aborted!!!\n", imgstr, brdstr); + rc = -1; + } else + rc = 0; + } + } + + return rc; +#else + return 0; +#endif /* DDR_TYPE_CHECK */ +} + +uint64_t getAvailImgSpace(int update_img_idx) +{ + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + return(nandGetAvailImgSpace(update_img_idx)); + break; + case FLASH_INFO_FLAG_EMMC: + return(emmcGetAvailImgSpace(update_img_idx)); + break; + case FLASH_INFO_FLAG_NOR: + if( !isLegacyFlashLayout()) + { + //FIXME return whole flash size. + return(spinorGetAvailSpace(SPI_NOR_MTD)); + } + break; + default: + break; + } + return 0; +} + +uint64_t getAvailLoaderSpace(int update_img_idx) +{ + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + return(nandGetAvailLoaderSpace()); + break; + case FLASH_INFO_FLAG_EMMC: + //FIXME: Pass image index to emmc + return(emmcGetAvailLoaderSpace()); + break; + case FLASH_INFO_FLAG_NOR: + return( spinorGetAvailSpace(SPI_NOR_LOADER_MTD)); + break; + + default: + break; + } + return 0; +} + +int synchLoaderEnv( char * loader_fname ) +{ + char * in_mem_env = NULL; + FILE* file_ptr; + char * ptr = NULL; + int tmp_buf_len = 255; + char buffer[tmp_buf_len]; + uint64_t env_size; + char * retstr = NULL; + int ret = -1; + uint32_t env_magic = 0; + int bytes; + int written_bytes=0; + UBOOT_ENV_HDR * env_hdr = NULL; + char * boot_magic_ptr; + int len; + int i; + + /* Get env size */ + file_ptr = fopen(PROC_BOOT_MAGIC, "r"); + if( !file_ptr ) + { + printf("%s: Error, cannot open %s\n", __FUNCTION__, PROC_BOOT_MAGIC); + ret = -1; + goto exit_loader_synch; + } + retstr = fgets((char*)buffer, tmp_buf_len, file_ptr); + if( retstr ) + { + env_size = strtoul(buffer,&ptr, 10); + } + else + { + printf("%s: Error, Read failed from %s\n", __FUNCTION__, PROC_BOOT_MAGIC); + ret = -1; + goto exit_loader_synch; + } + fclose(file_ptr); + + /* Delete env_boot_magic in flash so that it is updated by bootloader on next boot */ + if(system("echo 'env_boot_magic=' > /proc/nvram/set")) + { + printf("%s: Error, Could not clear 'env_boot_magic' env variable\n", __FUNCTION__); + ret = -1; + goto exit_loader_synch; + } + sync(); + + /* Open and read the temp environment into memory */ + in_mem_env = malloc( env_size + sizeof(UBOOT_ENV_HDR)); + if( !in_mem_env ) + { + printf("%s: Error, failed to allocate memory for env!\n", __FUNCTION__); + ret = -1; + goto exit_loader_synch; + } + file_ptr = fopen(PROC_ENV_RAW, "r"); + if( !file_ptr ) + { + printf("%s: Error, cannot open %s\n", __FUNCTION__, PROC_ENV_RAW); + ret = -1; + goto exit_loader_synch; + } + bytes = fread(in_mem_env, 1, env_size + sizeof(UBOOT_ENV_HDR), file_ptr); + if( !bytes ) + { + printf("%s: Error, Read failed from %s\n", __FUNCTION__, PROC_ENV_RAW); + ret = -1; + goto exit_loader_synch; + } + fclose(file_ptr); + + /* Clear bootmagic in in_memory_copy of env if not already cleared + * This captures those cases where customers disable /proc/nvram/set */ + for( i=sizeof(UBOOT_ENV_HDR); imagic = UBOOT_ENV_MAGIC; + env_hdr->size = (uint32_t)env_size; + env_hdr->crc = pkgtb_getCrc32((unsigned char*)(in_mem_env + sizeof(UBOOT_ENV_HDR)), env_size-4, 0); + + /* Find environment in loader, overwrite it with current environment */ + file_ptr = fopen(loader_fname, "r+"); + if( !file_ptr ) + { + printf("%s: Error, cannot open %s\n", __FUNCTION__, loader_fname); + ret = -1; + goto exit_loader_synch; + } + while( fread((char*)&env_magic, 4, 1, file_ptr) ) + { + fseek( file_ptr, -4, SEEK_CUR ); + if( env_magic == UBOOT_ENV_MAGIC ) + { + printf("Found MAGIC at 0x%08x\n", (unsigned int)ftell(file_ptr)); + ret = fwrite( in_mem_env, 1, env_size, file_ptr); + if( !ret ) + { + printf("%s: Error, Write failed to %s\n", __FUNCTION__, loader_fname); + ret = -1; + goto exit_loader_synch; + } + + written_bytes+=env_size; + } + else + { + fseek( file_ptr, BOOT_MAGIC_OFFS, SEEK_CUR ); + } + } + + if( !written_bytes ) + { + printf("%s: Error loader environment not synched to current env!\n", __FUNCTION__); + ret = -1; + } + else + ret = 0; + +exit_loader_synch: + if( in_mem_env ) + free(in_mem_env); + + if( file_ptr ) + fclose(file_ptr); + + return ret; +} + +int getImageVersion(uint8_t *imagePtr, int imageSize, char *image_name, int image_name_len) +{ + int ret = -1; + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = nandGetImageVersion(imagePtr, imageSize, image_name, image_name_len); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = emmcGetImageVersion(imagePtr, imageSize, image_name, image_name_len); + break; + + default: + break; + } + return ret; +} + + +/*********************************************************************** + * Function Name: bcmFlash_getIdent + * Description : Get the ident value + * part : Partition to search, 1 for first, 2 for second, 3 for boot, 4 for non-boot + * key : ident key value, leave blank to return all ident values + * buf : buffer to return ident values + * len : length of passed buffer + * start : starting block to search, -1 means from beginning or partition, returns block where tag was found + * end : ending block to search, -1 means end of partition + * Returns : return size on success (0 if nothing found), -1 on failure + ***********************************************************************/ +#define TRAILER 2 + +int bcmFlash_getIdent(int part, int *start, int *end, const char *key, char *line, int len) +{ + int ret = 0; // total size of all entries + int boot = getBootPartition(); + char name[MAX_MTD_NAME_SIZE]; + char *buf; + FILE *fp; + int point, read; + int size; // size of entry + int blksize; + + UPDATE_FLASH_INFO(); + if ( (gFlashInfo == FLASH_INFO_FLAG_NAND) || + ( gFlashInfo == FLASH_INFO_FLAG_NOR) ) + { + int mtd_fd; + mtd_info_t *mtd; + + //FIXME should spinor flash return 0? + if( gFlashInfo == FLASH_INFO_FLAG_NOR) + mtd = get_mtd_device_handle(SPI_NOR_BOOTFS_MTD_NAME, &mtd_fd, 0); + else + mtd = get_mtd_device_handle("image", &mtd_fd, 0); + if (!mtd) + { + fprintf(stderr, "ERROR!!! Could not get image device handle\n"); + put_mtd_device(mtd, mtd_fd, -1); + return(-1); + } + + blksize = mtd->erasesize; + put_mtd_device(mtd, mtd_fd, -1); + + if (!blksize) + { + fprintf(stderr, "ERROR!!! Could not find block size\n"); + return(-1); + } + } + else if (gFlashInfo == FLASH_INFO_FLAG_EMMC) + { + blksize = 0x20000; // match NAND minimum block size + } + else + return(-1); + + if (gFlashInfo == FLASH_INFO_FLAG_NAND) + { + if( isLegacyFlashLayout() ) + { + if ( (part == boot) || (part == 3) ) + ret = get_mtd_device_name("image", name); + else + ret = get_mtd_device_name("image_update", name); + + if (ret < 0) + return(-1); + } + else + { + if ( (part == 1) || ((part == 3) && (boot == 1)) || ((part == 4) && (boot == 2)) ) + ret = get_mtd_device_name("bootfs1", name); + else + ret = get_mtd_device_name("bootfs2", name); + + if (ret < 0) + return(-1); + } + } + else if (gFlashInfo == FLASH_INFO_FLAG_EMMC) + { + if ( (part == 1) || ((part == 3) && (boot == 1)) || ((part == 4) && (boot == 2)) ) + strcpy(name, "/dev/bootfs1"); + else + strcpy(name, "/dev/bootfs2"); + } + else if (gFlashInfo == FLASH_INFO_FLAG_NOR) + { + //FIXME...NOR flash support single image + if( (part == 1) || (part == 3)) + ret = get_mtd_device_name(SPI_NOR_BOOTFS_MTD_NAME, name); + else + return(-1); + if (ret < 0) + return(-1); + } + else + return(-1); + + fp = fopen(name,"rb"); + if (fp == NULL) + { + fprintf(stderr, "ERROR!!! Could not open device %s\n", name); + return (-1); + } + + if ( (buf = malloc(blksize)) == 0) + { + fprintf(stderr, "ERROR!!! Could not allocate memory for block buffer\n"); + fclose(fp); + return(-1); + } + + if (key) + snprintf(name, MAX_MTD_NAME_SIZE, "$%s", key); + else + strcpy(name, "$"); + + if (*start >= 0) + fseek(fp, blksize * *start, SEEK_SET); + else + *start = 0; + + ret = 0; + while ( ((*end < 0) || (*start <= *end)) && ((read = fread(buf, 1, blksize, fp)) != 0) ) + { + for(point = 0; (point < (read - (strlen(name) + TRAILER))); point++) + { // search block for version string + if (!memcmp(buf + point, name, strlen(name))) + { + size = strlen(name); + + // check for valid tag + while ( ((point + size) < (read - TRAILER)) && + ( ( (*(buf + point + size) >= 'A') && (*(buf + point + size) <= 'Z') ) || + ( (*(buf + point + size) >= 'a') && (*(buf + point + size) <= 'z') ) ) ) + { + size++; + } + + if ( ( point+size < (read - TRAILER) ) && (*(buf + point + size) != ':') ) + continue; + + while ( ((point + size) < (read - TRAILER)) && + (*(buf + point + size) >= ' ') && (*(buf + point + size) <= '~') ) + { // continue search for valid entry + if (!memcmp(buf + point + size, " $", TRAILER)) + { // found terminator and thus entry + size += TRAILER; + + if (size <= len) + { + //memcpy(&line[ret], buf + point, size); + snprintf(&line[ret], len, "%.*s", size, buf + point); + + len -= size; + } + + ret += size; + + if (key) + goto DONE; + + point += size; + break; + } + + size++; + } + } + } + + (*start)++; + } +DONE: + fclose(fp); + free(buf); + + return( ret ); +} + + +/*********************************************************************** + * Function Name: getBootPartition + * Description : Returns the booted partition. + * Returns : boot partition or -1 for failure + ***********************************************************************/ +#include +#include "util.c" + +int getBootPartition( void ) +{ + int ret = -1; + + char *blob; + int len; + int *value = 0; + int offset; + + blob = utilfdt_read("/sys/firmware/fdt", NULL); + if (blob) + { + if ( (offset = fdt_path_offset(blob, "/chosen")) >= 0 ) + { + if ( (value = (int *)fdt_getprop(blob, offset, "active_image", &len)) ) + { + if ( (ret = fdt32_to_cpu(*(fdt32_t *)value)) && (ret > 0) && (ret < 3) ) + return(ret); + } + } + } + + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = nandGetBootPartition(); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = emmcGetBootPartition(); + break; + + case FLASH_INFO_FLAG_NOR: + //FIXME spi nor flash only support single image. + ret = 1; + break; + + default: + break; + } + return ret; +} + + +/*********************************************************************** + * Function Name: getUpgradePartition + * Description : Returns the upgrade partition. + * Returns : upgrade partition + ***********************************************************************/ +int getUpgradePartition( void ) +{ + int part = getBootPartition(); + UPDATE_FLASH_INFO(); + if( (gFlashInfo != FLASH_INFO_FLAG_NOR) && (part != -1) ) + part = ((part==1)?2:1); + + return part; +} + +static unsigned int pkgtb_getCrc32(const unsigned char *pdata, unsigned int size, unsigned int crc_initial) +{ + unsigned int crc_final = genUtl_getCrc32(pdata, size, crc_initial ^ 0xffffffff) ^ 0xffffffff; + return crc_final; +} + +static int validate_metadata(MDATA *mdatap, int * committed, int *valid, int *seq) +{ + int valid_img_idx[2] = {0}; + int committed_idx = 0; + int seq_img_idx[2] = {-1}; + uint32_t crc; + int ret = 0; + int i; + char * commitp = mdatap->mdata_obj.data; + char * validp = commitp + strlen(commitp) + 1; + char * seqp = validp + strlen(validp) + 1; + crc = pkgtb_getCrc32((unsigned char*)mdatap->mdata_obj.data, (mdatap->size - 4) & 0xffff, 0); + + if( crc == mdatap->mdata_obj.crc ) + { + sscanf(commitp,"COMMITTED=%d", &committed_idx); + sscanf(validp,"VALID=%d,%d", &valid_img_idx[0], &valid_img_idx[1]); + //FIXME: Magic numbers + for( i=0; i<2; i++ ) + { + if( valid_img_idx[i] ) + valid[valid_img_idx[i]-1] = valid_img_idx[i]; + } + *committed = committed_idx; + + // preset the sequence numbers incase the field doesn't exist + if ((*committed == 1) && valid[0]) + { + seq[0] = 1; + if (valid[1]) + seq[1] = 0; + } + else if ((*committed == 2) && valid[1]) + { + seq[1] = 1; + if (valid[0]) + seq[0] = 0; + } + + sscanf(seqp,"SEQ=%d,%d", &seq_img_idx[0], &seq_img_idx[1]); + for( i=0; i<2; i++ ) + { + if( seq_img_idx[i] != -1) + seq[i] = seq_img_idx[i]; + } + + printf("rd_metadata: committed %d valid %d,%d seq %d,%d\n", *committed, valid[0], valid[1], seq[0], seq[1]); + } + else + { + printf("ERROR: metadata crc failed! exp: 0x%08x calc: 0x%08x\n", mdatap->mdata_obj.crc, crc); + *committed = 0; + valid[0] = 0; + valid[1] = 0; + ret = -1; + } + return ret; +} + +static int set_metadata_val( int * committed, int * valid, int * seq ) +{ + MDATA * mdatap; + uint32_t crc; + int i, mdata_idx; + int ret = -1; + UPDATE_FLASH_INFO(); + + mdatap = (MDATA *)malloc(PKGTB_METADATA_RDWR_SIZE); + mdatap->word0 = PKGTB_METADATA_SIZE; + mdatap->size = PKGTB_METADATA_SIZE; + i = sprintf((char*)mdatap->mdata_obj.data, "COMMITTED=%d",*committed) + 1; + i = i + sprintf((char*)&mdatap->mdata_obj.data[i], "VALID=%d,%d",valid[0],valid[1]) + 1; + i = i + sprintf((char*)&mdatap->mdata_obj.data[i], "SEQ=%d,%d",seq[0],seq[1]) + 1; + mdatap->mdata_obj.data[i] = '\0'; + crc = pkgtb_getCrc32((unsigned char*)mdatap->mdata_obj.data, (mdatap->size - 4) & 0xffff, 0); + memcpy(&mdatap->mdata_obj.crc, &crc, sizeof(crc)); + + printf("wr_metadata: committed %d valid %d,%d seq %d,%d\n", *committed, valid[0], valid[1], seq[0], seq[1]); + + //FIXME: Magic numbers + for( mdata_idx=1; mdata_idx<=2; mdata_idx++ ) + { + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = setNandMetadata((char*)mdatap, PKGTB_METADATA_RDWR_SIZE, mdata_idx); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = setEmmcMetadata((char*)mdatap, PKGTB_METADATA_RDWR_SIZE, mdata_idx); + break; + + case FLASH_INFO_FLAG_NOR: + //FIXME nor not support metadata + ret = 0; + break; + default: + break; + } + } + + free(mdatap); + return ret; +} + +static int get_metadata_val( int * committed, int * valid, int * seq) +{ + MDATA * mdatap = (MDATA *)malloc(PKGTB_METADATA_MAX_SIZE); + int ret = -1; + int num_bytes_read = 0; + int mdata_idx; + UPDATE_FLASH_INFO(); + + //FIXME: Magic numbers + for( mdata_idx=1; (mdata_idx<=2) && (ret < 0); mdata_idx++ ) + { + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + num_bytes_read = getNandMetadata( (char*)mdatap, PKGTB_METADATA_RDWR_SIZE, mdata_idx); + break; + + case FLASH_INFO_FLAG_EMMC: + num_bytes_read = getEmmcMetadata( (char*)mdatap, PKGTB_METADATA_RDWR_SIZE, mdata_idx); + break; + + case FLASH_INFO_FLAG_NOR: + //FIXME SPI NOR not support + free(mdatap); + return ret; + break; + + default: + break; + } + + if( num_bytes_read >= PKGTB_METADATA_SIZE ) + ret = validate_metadata(mdatap, committed, valid, seq); + else + fprintf(stderr, "ERROR!!! unable to retrieve metadata%d!", mdata_idx); + } + free(mdatap); + + if( ret ) + fprintf(stderr, "ERROR!!! unable to retrieve/parse metadata!"); + + return ret; +} + +static int getImgCommitStatus( int img_idx, char * commit_flag ) +{ + int committed_img = 0; + //FIXME: Magic numbers + int valid_imgs[2] = {0}; + int seq_imgs[2] = {-1}; + int ret = get_metadata_val(&committed_img, valid_imgs, seq_imgs); + + if (ret) + return(ret); + + if( committed_img == img_idx ) + *commit_flag = '1'; + else + *commit_flag = '0'; + return 0; +} + +static int setImgCommitStatus( int img_idx , char * commit_flag) +{ + int committed_img = 0; + //FIXME: Magic numbers + int valid_imgs[2] = {0}; + int seq_imgs[2] = {-1}; + int ret = get_metadata_val(&committed_img, valid_imgs, seq_imgs); + + if (ret) + return(ret); + + if( *commit_flag == '1' ) + { + valid_imgs[img_idx-1] = img_idx; + committed_img = img_idx; + } + else + { + if( committed_img == img_idx ) + committed_img = 0; + } + + set_metadata_val(&committed_img, valid_imgs, seq_imgs); + return 0; +} + +int setImgValidStatus( int img_idx, int * valid) +{ + int committed_img = 0; + //FIXME: Magic numbers + int valid_imgs[2] = {0}; + int seq_imgs[2] = {-1}; + int ret = get_metadata_val(&committed_img, valid_imgs, seq_imgs); + + if (ret) + return(ret); + + if( *valid ) + valid_imgs[img_idx-1] = img_idx; + else + valid_imgs[img_idx-1] = 0; + + set_metadata_val(&committed_img, valid_imgs, seq_imgs); + return 0; +} + +int getImgValidStatus( int img_idx, int * valid) +{ + int committed_img = 0; + //FIXME: Magic numbers + int valid_imgs[2] = {0}; + int seq_imgs[2] = {-1}; + int ret = get_metadata_val(&committed_img, valid_imgs, seq_imgs); + + if (ret) + return(ret); + + if( valid_imgs[img_idx-1] == img_idx ) + *valid = 1; + else + *valid = 0; + return 0; +} + +int setImgSeqNum( int img_idx, int seq) +{ + int committed_img = 0; + //FIXME: Magic numbers + int valid_imgs[2] = {0}; + int seq_imgs[2] = {-1}; + int ret = get_metadata_val(&committed_img, valid_imgs, seq_imgs); + + if (ret) + return(ret); + + if( valid_imgs[img_idx-1] ) + seq_imgs[img_idx-1] = seq; + + set_metadata_val(&committed_img, valid_imgs, seq_imgs); + return 0; +} + +int getImgSeqNum( int img_idx, int * seq) +{ + int committed_img = 0; + //FIXME: Magic numbers + int valid_imgs[2] = {0}; + int seq_imgs[2] = {-1}; + int ret = get_metadata_val(&committed_img, valid_imgs, seq_imgs); + + if (ret) + return(ret); + + *seq = seq_imgs[img_idx-1]; + + return 0; +} + + +/*********************************************************************** + * Function Name: commit + * Description : Gets/sets the commit flag for an image. + * Returns : 0 for success or -1 for failure + ***********************************************************************/ +int commit( int partition, char *string ) +{ + int ret = -1; + UPDATE_FLASH_INFO(); + + if( isLegacyFlashLayout()) + { + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = nandCommit(partition, string); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = emmcCommit(partition, string); + break; + + default: + break; + } + } + else + { + int write = (*string != 0); + /* New flash layout */ + flashutil_debug("%s: Write:%d, part:%d\n", __FUNCTION__, write, partition); + if( write ) + ret = setImgCommitStatus(partition, string); + else + ret = getImgCommitStatus(partition, string); + } + return ret; +} + + +/*********************************************************************** + * devCtl_setImageState - for all flash types (safer to call this) + * setBootImageState - for NAND or EMMC flash only + * Description : Persistently sets the state of an image update. + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int devCtl_setImageState(int state) +{ + unsigned int flag=0; + + getFlashInfo(&flag); + if (flag & (FLASH_INFO_FLAG_NAND | FLASH_INFO_FLAG_EMMC)) // NAND flash, no need to dig into kernel space + return(setBootImageState(state)); + else + { + if( norIsNewFlashLayout()) + return 0; + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, state, NULL) ); + } +} + +int getBootReason(void) +{ + char buffer[64]; + int rc; + + FILE *fp; + + if (!(fp = fopen("/proc/bootstate/reset_reason", "r"))) + { + printf("%s: Error, cannot open %s\n", __FUNCTION__, "/proc/bootstate/reset_reason"); + return(-1); + } + + if (!fgets((char*)buffer, 64, fp)) + { + fclose(fp); + printf("%s: Error, Read failed from %s\n", __FUNCTION__, "/proc/bootstate/reset_reason"); + return(-1); + } + + fclose(fp); + + rc = strtoul(buffer, NULL, 16); + + return(rc); +} + +int setBootReason( int reason ) +{ + char command[64]; + int rc; + + snprintf(command, sizeof command, "echo 0x%x > /proc/bootstate/reset_reason", reason); + rc = system(command); + + return(rc); +} + +int setBootImageState( int newState ) +{ + int ret = -1; + int currState; + int seq1 = -1; + int seq2 = -1; + char commitflag1 = 0; + char commitflag2 = 0; + int pureubi1; + int pureubi2; + + /* Get current boot state variables */ + currState = getBootImageState(); + seq1 = getSequenceNumber(1); + seq2 = getSequenceNumber(2); + pureubi1 = commit(1, &commitflag1); + pureubi2 = commit(2, &commitflag2); + +#ifdef NO_AUTOCOMMIT_IMAGE + if (newState == BOOT_SET_NEW_IMAGE) + { + FILE *fp; + + fp = fopen("/data/commit_image_after_reboot","w"); + + if (!IS_NULL(fp)) + { + fclose(fp); + printf("Not committing image now but will do so after successful reboot to Linux\n"); + newState = BOOT_SET_NEW_IMAGE_ONCE; + } + else + printf("ERROR!!! Could not create data file, committing image now\n"); + } +#endif + + if ((seq1 == 0) && (seq2 == 999)) + seq1 = 1000; + if ((seq2 == 0) && (seq1 == 999)) + seq2 = 1000; + + switch(newState) + { // convert state to OMCI states + case BOOT_SET_NEW_IMAGE: + if( seq1 > seq2 ) + newState = BOOT_SET_PART1_IMAGE; + else + newState = BOOT_SET_PART2_IMAGE; + break; + + case BOOT_SET_OLD_IMAGE: + if( seq2 > seq1 ) + newState = BOOT_SET_PART1_IMAGE; + else + newState = BOOT_SET_PART2_IMAGE; + break; + + case BOOT_SET_NEW_IMAGE_ONCE: + if( seq1 > seq2 ) + newState = BOOT_SET_PART1_IMAGE_ONCE; + else + newState = BOOT_SET_PART2_IMAGE_ONCE; + break; + + case BOOT_SET_OLD_IMAGE_ONCE: + if( seq2 > seq1 ) + newState = BOOT_SET_PART1_IMAGE_ONCE; + else + newState = BOOT_SET_PART2_IMAGE_ONCE; + break; + + default: + break; + } + + if( currState == newState ) + return(0); + + if (isLegacyFlashLayout() && !pureubi1 && !pureubi2) + { // two pureUBI images + switch(newState) + { + case BOOT_SET_PART1_IMAGE: + case BOOT_SET_PART2_IMAGE_ONCE: + commit(1, "1"); + if (seq2 > seq1) + commit(2, "0"); + break; + + case BOOT_SET_PART2_IMAGE: + case BOOT_SET_PART1_IMAGE_ONCE: + commit(2, "1"); + if (seq1 > seq2) + commit(1, "0"); + break; + + default: + break; + } + + if ( (newState == BOOT_SET_PART1_IMAGE_ONCE) || (newState == BOOT_SET_PART2_IMAGE_ONCE) ) + { // set bit to boot the inactive image + getset_boot_inactive_image(1); + } + } + + if (!isLegacyFlashLayout()) + { + int valid1; + int valid2; + + getImgValidStatus(1, &valid1); + getImgValidStatus(2, &valid2); + + switch(newState) + { // new layout works differently, there's only a single commit value so committing one image automatically uncommits the other + case BOOT_SET_PART1_IMAGE: + case BOOT_SET_PART2_IMAGE_ONCE: + if ((commitflag1 != '1') && valid1) + commit(1, "1"); + break; + + case BOOT_SET_PART2_IMAGE: + case BOOT_SET_PART1_IMAGE_ONCE: + if ((commitflag2 != '1') && valid2) + commit(2, "1"); + break; + + default: + break; + } + + if (valid1 && valid2 && ((newState == BOOT_SET_PART1_IMAGE_ONCE) || (newState == BOOT_SET_PART2_IMAGE_ONCE)) ) + { // set bit to boot the inactive image + setBootReason(BCM_BOOT_REASON_ACTIVATE); + } + else + setBootReason(0); + + } + + { /* NAND flash, old method of boot_state */ + FILE *fp; + char state_name[] = "/data/" NAND_BOOT_STATE_FILE_NAME; + + /* Update the image state persistently using "new image" and "old image" + * states. Convert "partition" states to "new image" state for + * compatibility with the non-OMCI image update. + */ + switch(newState) + { // convert OMCI state to internal state + case BOOT_SET_PART1_IMAGE: + if( seq1 > seq2 ) + newState = BOOT_SET_NEW_IMAGE; + else + newState = BOOT_SET_OLD_IMAGE; + break; + + case BOOT_SET_PART2_IMAGE: + if( seq2 > seq1 ) + newState = BOOT_SET_NEW_IMAGE; + else + newState = BOOT_SET_OLD_IMAGE; + break; + + case BOOT_SET_PART1_IMAGE_ONCE: + if( seq1 > seq2 ) + newState = BOOT_SET_NEW_IMAGE_ONCE; + else + newState = BOOT_SET_OLD_IMAGE_ONCE; + break; + + case BOOT_SET_PART2_IMAGE_ONCE: + if( seq2 > seq1 ) + newState = BOOT_SET_NEW_IMAGE_ONCE; + else + newState = BOOT_SET_OLD_IMAGE_ONCE; + break; + + default: + break; + } + + /* Remove old file: + * This must happen before a new file is created so that the new file- + * name will have a higher version in the FS, this is also the reason + * why renaming might not work well (higher version might exist as + * deleted in FS) However this discrimination should be fixed now in CFE */ + { + int rc; + char command[64]; + + state_name[strlen(state_name) - 1] = '*'; + snprintf(command, sizeof command, "rm %s >/dev/null 2>&1", state_name); // suppress command output in case no files were found to delete + rc = system(command); + if (rc < 0) + { + fprintf(stderr, "rm command failed.\n"); + } + } + + /* Create new state file name. */ + state_name[strlen(state_name) - 1] = newState; + + fp = fopen(state_name,"w"); + + if (!IS_NULL(fp)) + { + fwrite(state_name, strlen(state_name), 1, fp); + + fclose(fp); + } + else + printf("Unable to open '%s'.\n", state_name); + + ret = 0; + } + + return( ret ); +} + + +/*********************************************************************** +* devCtl_getImageState - for all flash types (safer to call this) +* getBootImageState - for NAND or EMMC flash only + * Description : Gets the state of an image update from flash. + * Returns : state constant or -1 for failure + ***********************************************************************/ +int devCtl_getImageState(void) +{ + unsigned int flag=0; + + getFlashInfo(&flag); + if (flag & (FLASH_INFO_FLAG_NAND | FLASH_INFO_FLAG_EMMC)) + return(getBootImageState()); + else + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, BOOT_GET_BOOT_IMAGE_STATE, NULL) ); +} + +int getBootImageState(void) +{ + int seq1 = -1; + int seq2 = -1; + char commitflag1 = 0; + char commitflag2 = 0; + int ret = (getBootPartition() == 1) ? BOOT_SET_PART1_IMAGE : BOOT_SET_PART2_IMAGE; + int pureubi1 = commit(1, &commitflag1); + int pureubi2 = commit(2, &commitflag2); + + seq1 = getSequenceNumber(1); + seq2 = getSequenceNumber(2); + + if ((seq1 == 0) && (seq2 == 999)) + seq1 = 1000; + if ((seq2 == 0) && (seq1 == 999)) + seq2 = 1000; + + /* Handle new flash layout */ + if( !isLegacyFlashLayout() ) + { + if (commitflag1 == '1') + { + if (getBootReason() == BCM_BOOT_REASON_ACTIVATE) + ret = BOOT_SET_PART2_IMAGE_ONCE; + else + ret = BOOT_SET_PART1_IMAGE; + } + else if (commitflag2 == '1') + { + if (getBootReason() == BCM_BOOT_REASON_ACTIVATE) + ret = BOOT_SET_PART1_IMAGE_ONCE; + else + ret = BOOT_SET_PART2_IMAGE; + } + + return ret; + } + + if (!pureubi1 && !pureubi2) + { // two pureUBI images, boot state undefined if neither flag is 1 + if (seq1 > seq2) + { + if (commitflag1 == '1') + ret = BOOT_SET_PART1_IMAGE; + else if (commitflag2 == '1') + ret = BOOT_SET_PART2_IMAGE; + } + else + { + if (commitflag2 == '1') + ret = BOOT_SET_PART2_IMAGE; + else if (commitflag1 == '1') + ret = BOOT_SET_PART1_IMAGE; + } + + if (getset_boot_inactive_image(-1) == 1) + { + if (ret == BOOT_SET_PART1_IMAGE) + ret = BOOT_SET_PART2_IMAGE_ONCE; + if (ret == BOOT_SET_PART2_IMAGE) + ret = BOOT_SET_PART1_IMAGE_ONCE; + } + } + else if ((seq1 != -1) && (seq2 != -1)) + { // two images and at least one JFFS2 image, boot state is in data partition + /* NAND flash */ + char states[] = {BOOT_SET_NEW_IMAGE, BOOT_SET_OLD_IMAGE, + BOOT_SET_NEW_IMAGE_ONCE, BOOT_SET_OLD_IMAGE_ONCE}; + char boot_state_name[] = "/data/" NAND_BOOT_STATE_FILE_NAME; + int i; + + /* The boot state is stored as the last character of a file name on + * the data partition, /data/boot_state_X, where X is + * BOOT_SET_NEW_IMAGE, BOOT_SET_OLD_IMAGE, BOOT_SET_NEW_IMAGE_ONCE. + */ + for( i = 0; i < (int)sizeof(states); i++ ) + { + FILE *fp; + + boot_state_name[strlen(boot_state_name) - 1] = states[i]; + + fp = fopen(boot_state_name,"r"); + + if (fp != NULL) + { + fclose(fp); + + ret = (int) states[i]; + break; + } + } + + switch(ret) + { // convert state to OMCI states + case BOOT_SET_NEW_IMAGE: + if( seq1 > seq2 ) + ret = BOOT_SET_PART1_IMAGE; + else + ret = BOOT_SET_PART2_IMAGE; + break; + + case BOOT_SET_OLD_IMAGE: + if( seq2 > seq1 ) + ret = BOOT_SET_PART1_IMAGE; + else + ret = BOOT_SET_PART2_IMAGE; + break; + + case BOOT_SET_NEW_IMAGE_ONCE: + if( seq1 > seq2 ) + ret = BOOT_SET_PART1_IMAGE_ONCE; + else + ret = BOOT_SET_PART2_IMAGE_ONCE; + break; + + case BOOT_SET_OLD_IMAGE_ONCE: + if( seq2 > seq1 ) + ret = BOOT_SET_PART1_IMAGE_ONCE; + else + ret = BOOT_SET_PART2_IMAGE_ONCE; + break; + + default: + break; + } + } + + return( ret ); +} + + +int devCtl_getBootedImageId(void) +{ // this call is ok as the "0" value does not call getSequenceNumber which won't work with pureUBI images + return( (int) devCtl_boardIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 0, BOOT_GET_BOOTED_IMAGE_ID, NULL) ); +} + +/*********************************************************************** + * devCtl_getBootedImagePartition -- for all flash types (safer to call this) + * getBootedValue for NAND and EMMC types only. + * Description : Gets the state of an image update from flash. + * Returns : state constant or -1 for failure + ***********************************************************************/ +int devCtl_getBootedImagePartition(void) +{ + unsigned int flag=0; + + getFlashInfo(&flag); + if (flag & (FLASH_INFO_FLAG_NAND | FLASH_INFO_FLAG_EMMC)) + return(getBootedValue()); + else + return( (int) devCtl_boardDriverIoctl(BOARD_IOCTL_BOOT_IMAGE_OPERATION, + 0, NULL, 1, BOOT_GET_BOOTED_IMAGE_ID, NULL) ); +} + +int isLegacyFlashLayout(void) +{ + int ret = -1; + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = nandIsLegacyFlashLayout(); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = emmcIsLegacyFlashLayout(); + break; + + case FLASH_INFO_FLAG_NOR: + ret = !norIsNewFlashLayout(); + break; + + default: + break; + } + return ret; +} + +int getBootedValue(void) +{ + int ret = -1; + UPDATE_FLASH_INFO(); + switch( gFlashInfo ) + { + case FLASH_INFO_FLAG_NAND: + ret = nandGetBootedValue(); + break; + + case FLASH_INFO_FLAG_EMMC: + ret = emmcGetBootedValue(); + break; + + default: + break; + } + return ret; +} +#endif /* DESKTOP_LINUX */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil.h new file mode 100755 index 00000000000..73a28759380 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil.h @@ -0,0 +1,266 @@ +/*********************************************************************** + * + * Copyright (c) 2011 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2011:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + + +#ifndef _BCM_FLASHUTIL_H__ +#define _BCM_FLASHUTIL_H_ + +/*!\file bcm_flashutil.h + * \brief Public header file for the bcm_flashutil library. + */ + +#include + +#define FLASH_INFO_FLAG_NOR 0x0001 +#define FLASH_INFO_FLAG_NAND 0x0002 +#define FLASH_INFO_FLAG_EMMC 0x0004 + +#define PSI_FILE_NAME "/data/psi" +#define PSI_BACKUP_FILE_NAME "/data/psibackup" +#define SCRATCH_PAD_FILE_NAME "/data/scratchpad" +#define SYSLOG_FILE_NAME "/data/syslog" +#define IMAGE_VERSION_FILE_NAME "image_version" + +#define MAX_MTD_NAME_SIZE 64 +#define MAX_PSI_FILE_NAME_LEN 64 + + +/*********************************************************************************** + * REBOOT REASON and STATUS * + ***********************************************************************************/ + +#define BCM_BOOT_REASON_REBOOT (0x00000000) +#define BCM_BOOT_REASON_ACTIVATE (0x00000001) +#define BCM_BOOT_REASON_PANIC (0x00000002) +#define BCM_BOOT_REASON_WATCHDOG (0x00000004) + +#define BCM_BOOT_PHASE_MASK (0x000000F0) +#define BCM_BOOT_PHASE_UBOOT (0x00000010) +#define BCM_BOOT_PHASE_LINUX_START (0x00000020) +#define BCM_BOOT_PHASE_LINUX_RUN (0x00000030) + +#define PCIE_RESET_STATUS 0x10000000 +#define SW_RESET_STATUS 0x20000000 +#define HW_RESET_STATUS 0x40000000 +#define POR_RESET_STATUS 0x80000000 +#define RESET_STATUS_MASK 0xF0000000 + + + +#define UBOOT_ENV_MAGIC 0x75456e76 +#define PROC_BOOT_MAGIC "/proc/environment/env_boot_magic" +#define BOOT_MAGIC_OFFS 4096 +#define PROC_ENV_RAW "/proc/environment/raw" + +typedef struct +{ + uint32_t magic; + uint32_t size; + uint32_t crc; +} UBOOT_ENV_HDR; + +/*********************************************************************************** + * NEW FLASH LAYOUT METADATA STRUCTS * + ***********************************************************************************/ +#define PKGTB_METADATA_SIZE 256 //FIXME: Must match uboot value +#define PKGTB_METADATA_RDWR_SIZE (PKGTB_METADATA_SIZE + 1024 ) //FIXME: Must match uboot value +#define PKGTB_METADATA_MAX_SIZE 4096 + +typedef struct +{ + unsigned int crc; + char data[1024]; +} __attribute__((__packed__)) env_t; + +typedef struct +{ + unsigned int word0; + unsigned int size; + env_t mdata_obj; +} __attribute__((__packed__)) MDATA; + + +/** Get info about the flash. Currently, just returns the type of flash, + * but in the future, could return more useful info. Note the results are + * cached, so that the second and subsequent calls just return the cached + * result. + * + * @flags (OUT) Bit field containing info about the flash type. + * + * @return CmsRet enum. + */ +int getFlashInfo(unsigned int *flags); + + +/** Non-cached version of the function. This is more expensive. Most + * callers should just call getFlashInfo(). + */ +int getFlashInfoUncached(unsigned int *flags); + + +/** Get total size of the flash + * + * @size (OUT) kilobyte(KB) + * + * @return BcmRet enum + */ +int getFlashTotalSize(unsigned int *size); + +/** Get the sequence number of the image + * + * @param image (IN) image number to get the sequence number from (1 or 2) + * + * @return int sequence number + */ +int devCtl_getSequenceNumber(int image); + + +int getSequenceNumber(int imageNumber); +int getNextSequenceNumber(int seqNumImg1, int seqNumImg2); + +/** Set the boot image state. + * @param state (IN) BOOT_SET_NEW_IMAGE, BOOT_SET_OLD_IMAGE, + * BOOT_SET_NEW_IMAGE_ONCE, + * BOOT_SET_PART1_IMAGE, BOOT_SET_PART2_IMAGE, + * BOOT_SET_PART1_IMAGE_ONCE, BOOT_SET_PART2_IMAGE_ONCE + * + * @return BcmRet enum. + */ +int devCtl_setImageState(int state); +int setBootImageState(int newState); + +/** Get the boot image state. + * + * @return BOOT_SET_PART1_IMAGE, BOOT_SET_PART2_IMAGE, + * BOOT_SET_PART1_IMAGE_ONCE, BOOT_SET_PART2_IMAGE_ONCE + * + */ +int devCtl_getImageState(void); +int getBootImageState(void); + + +/** Return the number of bytes available in the flash for storing an image. + * + * @return number of bytes. +*/ +unsigned int bcmImg_getImageFlashSize(void); + +unsigned int bcmImg_getBroadcomImageTagSize(void); + +unsigned char bcmImg_willFitInFlash(unsigned int imageSize); + + +/** Use some heuristics to determine if this is a config file (and not an + * image file). + * + *@ return 1 if likely to be config file, else 0. + */ +unsigned char bcmImg_isConfigFileLikely(const char *buf); + + +/** The following config file functions are for backward compatibility only. + * In reality, on NAND systems, these are just files, so there is no need + * to call these functions. + */ +unsigned int bcmImg_getConfigFlashSize(void); +unsigned int bcmImg_getRealConfigFlashSize(void); +unsigned char bcmImg_isBackupConfigFlashAvailable(void); + + +/** Get the booted image partition. + * + * @return BOOTED_PART1_IMAGE, BOOTED_PART2_IMAGE + */ +int devCtl_getBootedImagePartition(void); +int getBootedValue(void); + + +int readNvramData(void *pNvramData); +unsigned int otp_is_btrm_boot(void); +unsigned int otp_is_boot_secure(void); +unsigned int otp_is_boot_mfg_secure(void); +unsigned int get_chip_id(void); +unsigned int get_flash_type(void); + + +/** Get the booted image id. + * + * @return BOOTED_NEW_IMAGE, BOOTED_OLD_IMAGE + */ +int devCtl_getBootedImageId(void); + + +/** Recommended minimum size for getImageVersion. + * + * A imageversion string looks like this: $imageversion: 5041test3G0861904 $ + */ +#define IMAGE_VERSION_TAG_SIZE 64 + +/** Get image version string ("imageversion"). + * + * This function has support for legacy NAND flash and also some processing + * of the returned string. + * Recommend either using the higher layer cmsImg_ functions or the low level + * bcmFlash_getIdent() function below. + * + * @return number of bytes copied into verStr + */ +int devCtl_getImageVersion(int partition, char *verStr, int verStrSize); +int getImageVersion(uint8_t *imagePtr, int imageSize, char *image_name, + int image_name_len); + +/** Get the ident signature from a partition. + * @param part (IN) partition to search, 1=first, 2=second, 3=boot, 4=non-boot + * key (IN) ident key value, leave blank to return all ident values + * buf (OUT) buffer for return ident string + * len (IN) length of provided buffer + * + * @return size of string on success, 0 if nothing found, -1 for error + * if this value is greater than len, there was more found than + * could fit in the buffer + */ +int bcmFlash_getIdent(int part, int *start, int *end, const char *key, char *buf, int len); + + +int getBootPartition( void ); +int getUpgradePartition( void ); +int setImgValidStatus( int partition, int * status ); +int getImgValidStatus( int partition, int * status ); +int setImgSeqNum( int partition, int seq ); +int getImgSeqNum( int partition, int * seq ); +int commit( int partition, char *string ); +int writeImageToNand(unsigned char *string, int size); +int isLegacyFlashLayout(void); +uint64_t getAvailImgSpace(int update_img_idx); +uint64_t getAvailLoaderSpace(int update_img_idx); +int synchLoaderEnv(char * loader_fname); +uint64_t getSysfsBytes(char *pathname); + +#endif /* _BCM_FLASHUTIL_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_emmc.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_emmc.c new file mode 100644 index 00000000000..5ea18c6b95b --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_emmc.c @@ -0,0 +1,864 @@ +/*********************************************************************** + * <:copyright-BRCM:2007:DUAL/GPL:standard + * + * Copyright (c) 2007 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +#include +#include +#include // types +#include +#include +#include + + +#include "bcm_hwdefs.h" +#include "emmc_linux_defs.h" +#include "genutil_crc.h" +#include "bcm_flashutil.h" +#include "bcm_flashutil_private.h" +#include "bcm_flashutil_emmc.h" + +#include +#include // close + +#include "bcmTag.h" /* in shared/opensource/include/bcm963xx, for FILE_TAG */ +#include "board.h" /* in bcmdrivers/opensource/include/bcm963xx, for BCM_IMAGE_CFE */ +#include "flash_api.h" + +#include // for open +#include +#include +#include +#include + +#define NVRAM_PARSING_SUPPORT 0 /* Leave this disabled: Image update does not modify NVRAM */ +#if NVRAM_PARSING_SUPPORT +#include "../../../../cfe/cfe/board/common/include/bcm_btrm_common.h" +#endif + +#define IS_ERR_OR_NULL(x) ((x)==0) +#define IS_ERR(x) ((x)<0) +#define IS_NULL(x) ((x)==0) + +#define ERROR -1 +#define SUCCESS 0 + +#define EMMC_CFE_RAM_NAME NAND_CFE_RAM_NAME +#define EMMC_CFE_RAM_SECBT_NAME NAND_CFE_RAM_SECBT_NAME +#define EMMC_CFE_RAM_SECBT_MFG_NAME NAND_CFE_RAM_SECBT_MFG_NAME +#define EMMC_CFE_RAM_NAME_LEN strlen(EMMC_CFE_RAM_NAME) +#define EMMC_CFE_RAM_NAME_CMP_LEN (strlen(EMMC_CFE_RAM_NAME) - 3) + +#define CRC_LENGTH 4 + +/* Bits 5, 4, 3 of ext_csd[PARTITION_CONFIG(179)] */ +#define EMMC_BOOT_PART_SHIFT 3 +#define EMMC_BOOT_PART_MASK 0x7 + +#define be16_to_cpu(x) __be16_to_cpu(x) +#define be32_to_cpu(x) __be32_to_cpu(x) +#define cpu_to_be32(x) __cpu_to_be32(x) + +/* This struct describes the fixed header of a bootfs entry */ +typedef struct +{ + unsigned int nextEntryOffset; // Relative to this field + unsigned int dataOffset; // Relative to this field + unsigned int dataLength; + unsigned int hdrCrc; +} BOOTFS_ENTRY_FIXED_HDR; + +typedef enum +{ + BOOTFS_DATA_READ, + BOOTFS_DATA_WRITE, +} BOOTFS_DATA_OP; + + +/*********************************************************************** + * Function Name: metadata_dup + * Description : retrieve metadata from file in metadata bootfs + * Returns : Null - failure + * Note : Caller must free allocated metadata memory + ***********************************************************************/ +static char * metadata_dup ( int imageNumber, int index , int * metadata_size) +{ + FILE * fp; + char * metadata_ptr = NULL; + char mdata_dev_name[] = EMMC_DEV_PNAME_FMT_STR_MDATA; + + sprintf(mdata_dev_name, EMMC_DEV_PNAME_FMT_STR_MDATA, imageNumber, index); + fp = fopen(mdata_dev_name, "r"); + + if( !fp ) + { + printf("%s: Error opening %s!\n", __FUNCTION__, mdata_dev_name); + return metadata_ptr; + } + + /* Determine size of metadata */ + fseek(fp, 0L, SEEK_END); + *metadata_size = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + /* Allocate buffer to hold metadata */ + metadata_ptr = malloc(*metadata_size); + if( !metadata_ptr ) + { + printf("%s: Error allocating memory for metadata\n", __FUNCTION__); + return metadata_ptr; + } + + /* Read all metadata into memory */ + fread(metadata_ptr, 1, *metadata_size, fp); + if( ferror(fp) ) + { + printf("%s: Error reading %s!\n", __FUNCTION__, mdata_dev_name); + perror("metadata read error"); + free(metadata_ptr); + metadata_ptr = NULL; + } + fclose(fp); + + return metadata_ptr; +} + +/*********************************************************************** + * Function Name: metadata_commit_all + * Description : write metadata to all metadata partitions + * Returns : -1 - failure + * Note : Caller must free allocated metadata memory + ***********************************************************************/ +static int metadata_commit_all ( int imageNumber, char * metadata_ptr, int metadata_size) +{ + FILE * fp; + int i; + char mdata_dev_name[] = EMMC_DEV_PNAME_FMT_STR_MDATA; + int ret = -1; + + for( i=EMMC_IMG_IDX_START; i<=EMMC_NUM_MDATA; i++ ) + { + sprintf(mdata_dev_name, EMMC_DEV_PNAME_FMT_STR_MDATA, imageNumber, i); + + fp = fopen(mdata_dev_name, "r+"); + + if( !fp ) + { + printf("%s: Error opening %s!\n", __FUNCTION__, mdata_dev_name); + return ret; + } + + fseek(fp, 0L, SEEK_SET); + + /* write metadata to partition */ + fwrite(metadata_ptr, 1, metadata_size, fp); + if( ferror(fp) ) + { + printf("%s: Error writing %s !\n", __FUNCTION__, mdata_dev_name); + perror("metadata write error"); + } + else + ret = 0; + + fclose(fp); + } + + return ret; +} +/*********************************************************************** + * Function Name: rw_inmemory_metadata_data + * Description : retrieve data from metadata in memory + * Returns : -1 - failure + ***********************************************************************/ +static int rw_inmemory_metadata_data( char * metadata_ptr, char * filename, char * data + , uint32_t data_len, BOOTFS_DATA_OP op) +{ + BOOTFS_ENTRY_FIXED_HDR bootfs_entry_hdr; + uint8_t * bootfs_entry_data_ptr; + uint8_t * bootfs_entry_data_crc_ptr; + uint8_t filename_match = 0; + uint32_t bootfs_hdr_crc; + uint32_t data_crc = 0; + BOOTFS_ENTRY_FIXED_HDR * bootfs_entry_ptr; + + bootfs_entry_ptr = (BOOTFS_ENTRY_FIXED_HDR *)metadata_ptr; + + /* Search for matching bootfs entry */ + do + { + /* Copy over fixed header to avoid any misaligned fields */ + memcpy(&bootfs_entry_hdr, bootfs_entry_ptr, sizeof(BOOTFS_ENTRY_FIXED_HDR)); + + /* check if valid entry */ + if( !be32_to_cpu(bootfs_entry_hdr.nextEntryOffset) ) + { + printf("%s: Bootfs entry update failed! Matching bootfs entry not found", __FUNCTION__); + return -1; + } + + /* Check if hdr crc is correct */ + bootfs_hdr_crc = CRC32_INIT_VALUE; + bootfs_hdr_crc = genUtl_getCrc32( (void *)bootfs_entry_ptr, + offsetof(BOOTFS_ENTRY_FIXED_HDR,hdrCrc), bootfs_hdr_crc ); + if( be32_to_cpu(bootfs_entry_hdr.hdrCrc) != bootfs_hdr_crc ) + { + printf("%s: Bootfs entry update failed! Corrupt hdr_crc: 0x%08x, Expected: 0x%08x\n", + __FUNCTION__, bootfs_hdr_crc, be32_to_cpu(bootfs_entry_hdr.hdrCrc)); + return -1; + } + + /* See if filename matches */ + if( strcmp( filename, (char *)bootfs_entry_ptr + + sizeof(BOOTFS_ENTRY_FIXED_HDR)) == 0 ) + { + filename_match = 1; + } + else + { + /* Move on to the next entry */ + bootfs_entry_ptr = + (BOOTFS_ENTRY_FIXED_HDR *)((char *)&bootfs_entry_ptr->dataOffset + + be32_to_cpu(bootfs_entry_hdr.nextEntryOffset)); + } + + } while ( !filename_match ); + + /* Check if data_length matches, updates cannot change the data length */ + if( data_len != be32_to_cpu(bootfs_entry_hdr.dataLength) ) + { + printf("%s: Bootfs entry update failed! Incompatible data_length: %d, Required length: %d\n", + __FUNCTION__, data_len, be32_to_cpu(bootfs_entry_hdr.dataLength)); + return -1; + } + + bootfs_entry_data_ptr = (uint8_t *)&(bootfs_entry_ptr->dataLength) + + be32_to_cpu(bootfs_entry_hdr.dataOffset); + bootfs_entry_data_crc_ptr = bootfs_entry_data_ptr + + be32_to_cpu(bootfs_entry_hdr.dataLength); + data_crc = CRC32_INIT_VALUE; + + /* Data Write: Update data field */ + if( op == BOOTFS_DATA_WRITE ) + { + memcpy(bootfs_entry_data_ptr, data,be32_to_cpu(bootfs_entry_hdr.dataLength)); + } + + /* Compute data crc over filename, padding and data */ + data_crc = cpu_to_be32(genUtl_getCrc32( (uint8_t*)bootfs_entry_ptr + + sizeof(BOOTFS_ENTRY_FIXED_HDR), + (uint32_t)((uint8_t *)bootfs_entry_data_crc_ptr + - ((uint8_t*)bootfs_entry_ptr + sizeof(BOOTFS_ENTRY_FIXED_HDR))), + data_crc)); + + if( op == BOOTFS_DATA_WRITE ) + { + /* Data Write: Write the updated crc */ + *(unsigned int*)(bootfs_entry_data_crc_ptr) = data_crc; + } + else + { + /* Data Read: Check if data crc matches */ + if( data_crc == *(unsigned int*)bootfs_entry_data_crc_ptr ) + { + /* Read data field */ + memcpy(data, bootfs_entry_data_ptr, + be32_to_cpu(bootfs_entry_hdr.dataLength)); + } + else + { + printf("%s: Bootfs entry read failed! CRC mismatch: expected:0x%08x, actual:0x%08x\n", + __FUNCTION__, + *(unsigned int*)bootfs_entry_data_crc_ptr, + data_crc); + return -1; + } + + } + + return 0; +} + +/*********************************************************************** + * Function Name: rw_inmemory_metadata_data + * Description : retrieve data from metadata in filesystem + * Returns : -1 - failure + ***********************************************************************/ +static int rw_metadata_data( int image_number, char * filename, char * data, uint32_t data_len, BOOTFS_DATA_OP op) +{ + int i; + char * metadata_ptr = NULL; + int metadata_size = 0; + int ret = -1; + + /* Try both copies of metadata */ + for( i=EMMC_IMG_IDX_START; i<=EMMC_NUM_MDATA; i++ ) + { + /* retrieve metadata from file */ + metadata_ptr = metadata_dup(image_number, i, &metadata_size); + + if( metadata_ptr ) + { + /* Get/set data from/to inmemory metadata */ + ret = rw_inmemory_metadata_data( metadata_ptr, filename, data, data_len, op); + + if( (ret == 0) && (op == BOOTFS_DATA_WRITE)) + { + /* write metadata back to file */ + ret = metadata_commit_all( image_number, metadata_ptr, metadata_size ); + } + + /* Free malloced metadata */ + free(metadata_ptr); + metadata_ptr = NULL; + + /* Early exit if we were successfull */ + if( ret == 0 ) + break; + } + } + + return ret; +} + +/*********************************************************************** + * Function Name: emmcGetBootPartition + * Description : Gets boot partition number + * Returns : -1 - failure + ***********************************************************************/ +int emmcGetBootPartition(void) +{ + char rootfs_devname[256]={0}; + char rootfs_devname1[256]={0}; + char * rootfs_devidx; + char * rootfs_devidx1; + int len = 0; + int boot_partition = -1; + static int cached_boot_partition = -1; + FILE *fp; + + if (cached_boot_partition != -1) + { + return cached_boot_partition; + } + + /* Open the command for reading. */ + fp = popen("/etc/get_rootfs_dev.sh", "r"); + if (fp == NULL) { + printf("Failed to run /etc/get_rootfs_dev.sh command\n" ); + return 0; + } + + /* Read the output a line at a time - output it. */ + fgets(rootfs_devname, sizeof(rootfs_devname), fp); + len = strlen(rootfs_devname); + pclose(fp); + + if( len ) + { + len = readlink(EMMC_DEV_PNAME_ROOTFS(1), rootfs_devname1 + , sizeof(rootfs_devname1)-1); + if( len ) + { + /* Move pointer to start of mmc device index */ + rootfs_devidx = strstr(rootfs_devname , EMMC_DEV_LINUX_PREFIX); + rootfs_devidx1 = strstr(rootfs_devname1, EMMC_DEV_LINUX_PREFIX); + if( rootfs_devidx && rootfs_devidx1 ) + { + if( strcmp(rootfs_devidx, rootfs_devidx1) == 0 ) + { + /* /dev/root and /dev/rootfs1 point to same device */ + boot_partition = 1; + } + else + boot_partition = 2; + } + } + } + + cached_boot_partition = boot_partition; + return boot_partition; +} + +/*********************************************************************** + * Function Name: emmcGetNvramOffset + * Description : Get offset to nvram data in inmemory copy of cferom + * Returns : -1 - failure + ***********************************************************************/ +int emmcGetNvramOffset( char * cfe_start_addr ) +{ + int nvram_data_offset = 0; +#if NVRAM_PARSING_SUPPORT +#if defined(CONFIG_BCM963138) + /* Gen2 Image - fixed header sizes*/ + nvram_data_offset = BTRM_SBI_SIGNED_COT_ELEM_SIZE * 2 + + BTRM_SBI_AUTH_HDR_SIZE + + BTRM_SBI_UNAUTH_HDR_SIZE; +#else + /* Gen3 Image - variable header sizes*/ + SbiUnauthHdrBeginning *pUHdr; + SbiAuthHdrBeginning *pAuthHdr; + uint32_t hdr_size_bytes = 0; + + /* Determine size of auth/unauth headers */ + pUHdr = (SbiUnauthHdrBeginning *)cfe_start_addr; + hdr_size_bytes = pUHdr->hdrLen; + pAuthHdr = (SbiAuthHdrBeginning *)(cfe_start_addr + hdr_size_bytes); + hdr_size_bytes += pAuthHdr->hdrLen; + + /* Add offset to start of actual CFEROM image */ + nvram_data_offset += hdr_size_bytes; +#endif + + /* Add offset to NVRAM data */ + nvram_data_offset += NVRAM_DATA_REL_OFFSET; +#endif /* NVRAM_PARSING_SUPPORT */ + + return nvram_data_offset; +} + +/*********************************************************************** + * Function Name: emmcUpdateMdataSeqnum + * Description : Updates sequencenumber either in memory or in filesystem + * Args : (optional)mdata_ptr - pointer to inmemory metadata + * : (optional)image_num - image number of target partition + * : seq_num - sequence number + * Returns : -1 - failure + ***********************************************************************/ +int emmcUpdateMdataSeqnum( char * mdata_ptr, int image_num, int seq_num ) +{ + int ret = -1; + char fname[] = EMMC_CFE_RAM_NAME; + char data[4] = {0}; + + sprintf(data, "%03d", seq_num); + + if( mdata_ptr ) + { + ret = rw_inmemory_metadata_data( mdata_ptr, fname, data, 3, BOOTFS_DATA_WRITE); + } + else if( image_num ) + { + ret = rw_metadata_data( image_num, fname, data, 3, BOOTFS_DATA_WRITE); + } + + return ret; +} + +/*********************************************************************** + * Function Name: emmcUpdateMdataCommitFlag + * Description : Updates commit flag either in memory or in filesystem + * Args : (optional)mdata_ptr - pointer to inmemory metadata + * : (optional)image_num - image number of target partition + * : flag - flag value + * Returns : -1 - failure + ***********************************************************************/ +int emmcUpdateMdataCommitFlag(char * mdata_ptr, int image_num, int flag ) +{ + int ret = -1; + char fname[] = "committed"; + char data[4] = {0}; + + sprintf(data, "%d", flag); + + if( mdata_ptr ) + { + ret = rw_inmemory_metadata_data( mdata_ptr, fname, data, strlen(data), BOOTFS_DATA_WRITE); + } + else if( image_num ) + { + ret = rw_metadata_data( image_num, fname, data, strlen(data), BOOTFS_DATA_WRITE); + } + + return ret; +} + +/*********************************************************************** + * Function Name: emmcReadNvramDAta + * Description : Gets nvram data + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int emmcReadNvramData(void *nvramData) +{ + int ret = -1; + FILE *fp; + + fp = fopen(EMMC_DEV_PNAME_NVRAM, "rw"); + + if (fp != NULL) + { + fread(nvramData, 1, sizeof(NVRAM_DATA), fp); + + if( ferror(fp) ) + printf("%s: Error reading NVRAM data\n", __FUNCTION__); + else + ret = 0; + + fclose(fp); + } + else + printf("%s: Error opening NVRAM device\n", __FUNCTION__); + + return ret; +} + +/*********************************************************************** + * Function Name: emmcGetSequenceNumber + * Description : Gets sequence number of image + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int emmcGetSequenceNumber(int image_number) +{ + char fname[] = EMMC_CFE_RAM_NAME; + char seq_num[4] = {0}; + int seqNumber = -1; + int ret = -1; + + if( !emmcIsLegacyFlashLayout() ) + { + if (getImgSeqNum(image_number, &seqNumber)) + printf("%s: Error! Could not retrieve sequence number for image %d\n", __FUNCTION__, image_number); + return seqNumber; + } + + ret = rw_metadata_data( image_number, fname, seq_num, 3, BOOTFS_DATA_READ); + if( ret == 0 ) + { + seqNumber = atoi(seq_num); + } + else + { + printf("%s: Error! Could not retrieve sequence number for image %d\n", __FUNCTION__, image_number); + } + + return(seqNumber); +} + +/*********************************************************************** + * Function Name: emmcGetImageVersion + * Description : Gets imageversion + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int emmcGetImageVersion(uint8_t *imagePtr, int imageSize, char *image_name + , int image_name_len) +{ + int ret = -1; + + printf("%s: Error! function not implemented for EMMC\n", __FUNCTION__); + + return ret; +} + +/*********************************************************************** + * Function Name: emmcWriteBootImageState + * Description : Gets/sets the commit flag of an image. + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int emmcCommit( int partition, char *string ) +{ + int ret = -1; + char fname[] = "committed"; + + if( emmcIsLegacyFlashLayout()) + { + ret = rw_metadata_data(partition, fname, string, 1, (*string == 0) ? BOOTFS_DATA_READ : BOOTFS_DATA_WRITE); + + if( ret ) + printf("%s: Error! Could not access commit flag for image %d\n", __FUNCTION__, partition); + } + else + { + printf("ERROR!!! This function should not be called for NEW flash layout\n"); + } + + return( ret ); +} + +/*********************************************************************** + * Function Name: emmcUpdateSequenceNumber + * Description : updates the sequence number on the specified partition + * to be the highest. + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int emmcUpdateSequenceNumber(int incSeqNumPart, int seqPart1, int seqPart2) +{ + int ret = -1; + + if( !emmcIsLegacyFlashLayout() ) + { + printf("%s: WARNING:Function not implemented for new flash layout\n", __FUNCTION__); + } + + printf("%s: Error! function not implemented for EMMC\n", __FUNCTION__); + + return( ret ); +} + +/*********************************************************************** + * Function Name: emmcIsBootDevice + * Description : Determines whether boot device is emmc + * Returns : 0 - bootdevice is not emmc, 1 - bootdevice IS emmc + ***********************************************************************/ +int emmcIsBootDevice(void) +{ + int found = 0; +#ifndef DESKTOP_LINUX + FILE *fp; + char line[COMMAND_LINE_SIZE]={0}; + fp = popen("/etc/get_rootfs_dev.sh", "r"); + if (fp == NULL) { + printf("Failed to run /etc/get_rootfs_dev.sh command\n" ); + return 0; + } + + if(fgets(line, sizeof(line), fp)) + { + if( strstr(line, "mmcblk") ) + found = 1; + } + pclose(fp); +#endif + return found; +} + +/*********************************************************************** + * Function Name: emmcIsLegacyFlashLayout + * Description : Determines whether boot device is using legacy flash layout + * Returns : 1 - flashlayout is legacy + ***********************************************************************/ +int emmcIsLegacyFlashLayout(void) +{ + FILE *file = NULL; + file = fopen("/dev/nvram", "r"); + if(file) + { + fclose(file); + return 1; + } + return 0; +} + + +/*********************************************************************** + * Function Name: emmcGetBootedValue (devCtl_getBootedImagePartition) + * Description : Gets the which partition we booted from. + * Returns : state constant or -1 for failure + ***********************************************************************/ +int emmcGetBootedValue(void) +{ + int bootPartition = emmcGetBootPartition(); + + if( bootPartition == 1 ) + return BOOTED_PART1_IMAGE; + else if( bootPartition == 2 ) + return BOOTED_PART2_IMAGE; + else + return -1; +} + +/*********************************************************************** + * Function Name: emmcVerifyImageDDRType + * Description : Verify if image ddr type match board(nvram) ddr type. + * Returns : 0 success or -1 for failure + ***********************************************************************/ +int emmcVerifyImageDDRType(uint32_t imageFlags) +{ + NVRAM_DATA nvram; + int ret = -1; + + if( emmcReadNvramData(&nvram) == 0 ) + ret = verifyImageDDRType(imageFlags, &nvram); + + return ret; +} + +static uint64_t emmcGetPartSize( char * full_dev_path ) +{ + char cmd[128]; + char size[128]; + uint64_t size_bytes = 0; + FILE *fp; + + sprintf(cmd, "blockdev --getsize64 %s",full_dev_path); + + /* Open the command for reading. */ + fp = popen(cmd, "r"); + if (fp == NULL) { + printf("Failed to run command\n" ); + return size_bytes; + } + + /* Read the output a line at a time - output it. */ + fgets(size, sizeof(size), fp); + size_bytes += strtoull(size, NULL, 10); + + /* close */ + pclose(fp); + return size_bytes; +} + +int emmcGetBootPartIndex( void ) { + char cmd[128]; + char part_conf_str[128]; + char * part_conf_val = NULL; + int boot_part_index = 0; //Default points to first boot partition + FILE *fp; + + sprintf(cmd, "mmc extcsd read /dev/mmcblk0 | grep PARTITION_CONFIG"); + + /* Open the command for reading. */ + fp = popen(cmd, "r"); + if (fp == NULL) { + printf("Failed to run command\n" ); + return boot_part_index; + } + + /* Read the output a line at a time - output it. */ + fgets(part_conf_str, sizeof(part_conf_str), fp); + part_conf_val = strstr(part_conf_str, "0x"); + if( part_conf_val ) { + boot_part_index = (strtoull(part_conf_val, NULL, 16) >> EMMC_BOOT_PART_SHIFT) + & EMMC_BOOT_PART_MASK; + } + + /* Remap boot part number (1-based) to linux index (0-based) */ + if( boot_part_index ) + boot_part_index--; + + /* close */ + pclose(fp); + return boot_part_index; +} + +uint64_t emmcGetAvailLoaderSpace( void ) { + char full_part_name[128]; + uint64_t size_bytes = 0; + + sprintf(full_part_name, "/dev/mmcblk0boot%d", emmcGetBootPartIndex()); + size_bytes = emmcGetPartSize(full_part_name); + + return size_bytes; +} + +uint64_t emmcGetAvailImgSpace( int update_img_idx ) +{ + char full_part_name[128]; + char * partitions[] = {"bootfs","rootfs"}; + uint64_t size_bytes = 0; + + //FIXME: Magic numbers + for( int i=0; i<2; i++ ) + { + sprintf(full_part_name, "/dev/%s%d",partitions[i], update_img_idx); + size_bytes += emmcGetPartSize(full_part_name); + } + return size_bytes; +} + +int emmcGetFlashSize(unsigned int *psize __attribute__((unused))) +{ + char sysfs_path[128]; + uint64_t mmcblk0_size = 0; + uint64_t mmcblk0boot0_size = 0; + uint64_t mmcblk0boot1_size = 0; + uint64_t mmcblk0rpmb = 0; + + sprintf(sysfs_path, "/sys/class/block/mmcblk0/size"); + mmcblk0_size = getSysfsBytes(sysfs_path); + sprintf(sysfs_path, "/sys/class/block/mmcblk0boot0/size"); + mmcblk0boot0_size = getSysfsBytes(sysfs_path); + sprintf(sysfs_path, "/sys/class/block/mmcblk0boot1/size"); + mmcblk0boot1_size = getSysfsBytes(sysfs_path); + sprintf(sysfs_path, "/sys/class/block/mmcblk0rpmb/size"); + mmcblk0rpmb = getSysfsBytes(sysfs_path); + + *psize = (512*(mmcblk0_size+mmcblk0boot0_size+mmcblk0boot1_size+mmcblk0rpmb)/1024); + return 0; +} + + +int getEmmcMetadata( char * data, int size , int mdata_idx) +{ + char mdata_fname[128]; + FILE * mdata_fh; + int num_bytes = 0; + sprintf(mdata_fname, "/dev/metadata%d", mdata_idx); + mdata_fh = fopen(mdata_fname, "r"); + + if( mdata_fh ) + { + num_bytes = fread(data, 1, size, mdata_fh); + + if( ferror(mdata_fh) ) + { + printf("%s: Error fread metadata%d!\n", __FUNCTION__, mdata_idx); + num_bytes = 0; + } + + fclose(mdata_fh); + } + else + { + printf("%s: Error fopen metadata%d!\n", __FUNCTION__, mdata_idx); + } + + return num_bytes; +} + +int setEmmcMetadata( char * data, int size, int mdata_idx) +{ + FILE * fp; + char mdata_dev_name[] = EMMC_DEV_PNAME_FMT_STR_MDATA; + int ret = -1; + + sprintf(mdata_dev_name, "/dev/metadata%d", mdata_idx); + + fp = fopen(mdata_dev_name, "r+"); + + if( !fp ) + { + printf("%s: Error opening %s!\n", __FUNCTION__, mdata_dev_name); + return ret; + } + + fseek(fp, 0L, SEEK_SET); + + /* write metadata to partition */ + fwrite(data, 1, size, fp); + if( ferror(fp) ) + { + printf("%s: Error writing %s !\n", __FUNCTION__, mdata_dev_name); + perror("metadata write error"); + } + else + ret = 0; + + fflush(fp); + fsync(fileno(fp)); + fclose(fp); + + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_emmc.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_emmc.h new file mode 100644 index 00000000000..157ea41b214 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_emmc.h @@ -0,0 +1,57 @@ +/*********************************************************************** + * + * Copyright (c) 2007 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2011:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + + +#ifndef _BCM_FLASHUTIL_EMMC_H__ +#define _BCM_FLASHUTIL_EMMC_H_ +#include "emmc_linux_defs.h" + +int emmcReadNvramData(void *nvramData); +int emmcGetSequenceNumber(int imageNumber); +int emmcGetImageVersion(uint8_t *imagePtr, int imageSize, char *image_name, int image_name_len); +int emmcWriteBootImageState( int newState ); +int emmcReadBootImageState( void ); +int emmcUpdateSequenceNumber(int incSeqNumPart, int seqPart1, int seqPart2); +int emmcIsBootDevice(void); +int emmcGetBootedValue(void); +int emmcGetNvramOffset( char * cfe_start_addr ); +int emmcUpdateMdataSeqnum( char * mdata_ptr, int image_num, int seq_num ); +int emmcUpdateMdataCommitFlag(char * mdata_ptr, int image_num, int flag ); +int emmcGetBootPartition(void); +int emmcCommit( int partition, char *string ); +int emmcVerifyImageDDRType( uint32_t imageFlags ); +int emmcIsLegacyFlashLayout(void); +uint64_t emmcGetAvailImgSpace( int update_img_idx ); +uint64_t emmcGetAvailLoaderSpace( void ); +int setEmmcMetadata( char * data, int size, int mdata_idx ); +int getEmmcMetadata( char * data, int size , int mdata_idx); +int emmcGetFlashSize(unsigned int *psize); +int emmcGetBootPartIndex( void ); +#endif /* _BCM_FLASHUTIL_EMMC_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nand.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nand.c new file mode 100755 index 00000000000..df437ebd026 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nand.c @@ -0,0 +1,2820 @@ +/*********************************************************************** + * <:copyright-BRCM:2007:DUAL/GPL:standard + * + * Copyright (c) 2007 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +#include +#include +#include // types +#include +#include + +#include "genutil_crc.h" +#include "bcm_flashutil.h" +#include "bcm_flashutil_private.h" +#include "bcm_flashutil_nand.h" + +#include "bcm_btrm_gen3_common.h" + +#include +#include // close +#include "os_defs.h" + +#include "bcmTag.h" /* in shared/opensource/include/bcm963xx, for FILE_TAG */ +#include "board.h" /* in bcmdrivers/opensource/include/bcm963xx, for BCM_IMAGE_CFE */ +#include "flash_api.h" +/* map getCrc32 used in bcm_ubi.h to our userspace impl genUtl_getCrc32 */ +#define getCrc32 genUtl_getCrc32 +#include "bcm_ubi.h" +#include "bcm_ubi.c" + +#include // for open +#include +#include +#include +#include +#include +#include +#include + +#define IS_ERR_OR_NULL(x) ((x)==0) +#define IS_ERR(x) ((x)<0) +#define IS_NULL(x) ((x)==0) + +#define ERROR -1 +#define SUCCESS 0 + +#define NAND_CFE_RAM_NAME_LEN strlen(NAND_CFE_RAM_NAME) +#define NAND_CFE_RAM_NAME_CMP_LEN (strlen(NAND_CFE_RAM_NAME) - 3) +#define NAND_CFE_RAM_RSVD_BLK 9 + +/* #define FLASHUTIL_DEBUG 1 */ +#if defined(FLASHUTIL_DEBUG) +#define flashutil_debug(fmt, arg...) \ + fprintf(stderr, "%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#else +#define flashutil_debug(fmt, arg...) +#endif +#define flashutil_print(fmt, arg...) \ + fprintf(stderr, "%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#define flashutil_error(fmt, arg...) \ + fprintf(stderr, "ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + +#define CRC_LENGTH 4 + +#define je16_to_cpu(x) ((x).v16) +#define je32_to_cpu(x) ((x).v32) + + +static int exist_mtd_dev_nm(const char * check __attribute__((unused))) +{ +#ifndef DESKTOP_LINUX + FILE *fp; + char line[MAX_MTD_NAME_SIZE]; + char name[MAX_MTD_NAME_SIZE]; + char compare[MAX_MTD_NAME_SIZE]; + + if ( (fp = fopen("/proc/mtd","r")) == 0) + { + fprintf(stderr, "ERROR!!! Could not open /proc/mtd\n"); + return(0); + } + + snprintf(compare, sizeof(compare), "%s%s%s", "\"", check, "\""); + + while(fgets(line, sizeof(line), fp)) + { + sscanf(line, "%*s %*s %*s %s", name); + + if(!strcmp(name, compare)) + { + fclose(fp); + return(1); + } + } + + fclose(fp); + + return(0); +#else + return(1); +#endif /* DESKTOP_LINUX */ +} + + +int get_mtd_device_name(const char * check __attribute__((unused)), char * device __attribute__((unused))) +{ +#ifndef DESKTOP_LINUX + FILE *fp; + char mtdn[MAX_MTD_NAME_SIZE]; + char line[MAX_MTD_NAME_SIZE]; + char name[MAX_MTD_NAME_SIZE]; + char compare[MAX_MTD_NAME_SIZE]; + + if ( (fp = fopen("/proc/mtd","r")) == 0) + { + fprintf(stderr, "ERROR!!! Could not open /proc/mtd\n"); + return(0); + } + + snprintf(compare, sizeof(compare), "%s%s%s", "\"", check, "\""); + + while(fgets(line, sizeof(line), fp)) + { + sscanf(line, "%s %*s %*s %s", mtdn, name); + + if(!strcmp(name, compare)) + { + fclose(fp); + + mtdn[strlen(mtdn) - 1] = 0; // get rid of trailing colon + snprintf(device, MAX_MTD_NAME_SIZE, "%s%.10s", "/dev/", mtdn); + + return(1); + } + } + + fclose(fp); + return(0); +#else + return(1); +#endif +} + + +mtd_info_t * get_mtd_device_handle(const char * check, int * mtd_fd, int * mtdblock_fd) +{ +#ifndef DESKTOP_LINUX + mtd_info_t * mtd; + FILE *fp; + char mtdn[MAX_MTD_NAME_SIZE]; + char line[MAX_MTD_NAME_SIZE]; + char name[MAX_MTD_NAME_SIZE]; + char compare[MAX_MTD_NAME_SIZE]; + + if ( (mtd = malloc(sizeof(mtd_info_t))) == 0) + { + fprintf(stderr, "ERROR!!! Could not allocate memory for mtd structure!\n"); + return(0); + } + + if ( (fp = fopen("/proc/mtd","r")) == 0) + { + fprintf(stderr, "ERROR!!! Could not open /proc/mtd\n"); + free(mtd); + return(0); + } + + snprintf(compare, sizeof(compare), "%s%s%s", "\"", check, "\""); + + while(fgets(line, sizeof(line), fp)) + { + sscanf(line, "%s %*s %*s %s", mtdn, name); + + if(!strcmp(name, compare)) + { + fclose(fp); + + mtdn[strlen(mtdn) - 1] = 0; // get rid of trailing colon + + snprintf(name, MAX_MTD_NAME_SIZE, "%s%.10s", "/dev/", mtdn); + + if ((*mtd_fd = open(name, O_RDWR)) < 0) + { + fprintf(stderr, "ERROR!!! Could not open %s\n", name); + free(mtd); + return(0); + } + + if (ioctl(*mtd_fd, MEMGETINFO, mtd) < 0) + { // cannot MEMGETINFO for mtdblock devices + fprintf(stderr, "ERROR!!! Could not get MTD information!\n"); + close(*mtd_fd); + free(mtd); + return(0); + } + + flashutil_debug("MTD info: \n" + "type=0x%x, flags=0x%x, size=0x%x \n" + "erasesize=0x%x, writesize=0x%x, oobsize=0x%x", + mtd->type, mtd->flags, mtd->size, + mtd->erasesize, mtd->writesize, mtd->oobsize); + + if (mtdblock_fd) + { // proper writing whereby UBI takes care of erasing can only be done through mtdblock, does not work via mtd + snprintf(name,MAX_MTD_NAME_SIZE, "%s%.10s", "/dev/mtdblock", &mtdn[3]); // get rid of leading "mtd" + + if ((*mtdblock_fd = open(name, O_RDWR)) < 0) + { + fprintf(stderr, "ERROR!!! Could not open %s\n", name); + close(*mtd_fd); + free(mtd); + return(0); + } + } + + return(mtd); + } + } + + fclose(fp); + free(mtd); + printf("%s:MTD partition/device %s not opened\n", check, __FUNCTION__); + return(0); +#else + mtd_info_t * mtd; + + flashutil_print("MTD partition/device %s, mtdblock_fd %p", check, mtdblock_fd); + if ((mtd = malloc(sizeof(mtd_info_t))) == 0) + { + flashutil_error("malloc(mtd_info_t) failed"); + return(0); + } + + mtd->type = 0; + mtd->flags = 0; + mtd->size = 0x60000000; + mtd->erasesize = 0x20000; + mtd->writesize = 0; + mtd->oobsize = 0; + *mtd_fd = 0; + + flashutil_debug("MTD info: \n" + "type=0x%x, flags=0x%x, size=0x%x \n" + "erasesize=0x%x, writesize=0x%x, oobsize=0x%x", + mtd->type, mtd->flags, mtd->size, + mtd->erasesize, mtd->writesize, mtd->oobsize); + + return(mtd); +#endif +} + + +void put_mtd_device(mtd_info_t * mtd, int mtd_fd __attribute__((unused)), int mtdblock_fd __attribute__((unused))) +{ + flashutil_debug("mtd=%p, mtd_fd=%d", mtd, mtd_fd); + free(mtd); +#ifndef DESKTOP_LINUX + close(mtd_fd); + + if(mtdblock_fd >= 0) + close(mtdblock_fd); +#endif +} + +#ifndef DESKTOP_LINUX +/* Userspace mtdchar read function does not report NAND error, the reason for this is that the read function ignores a driver + * error and instead returns an incorrect read length code (the same length as was requested) and does not update errno. + * The kernel writers justification for this is that there is still useable data that could be retrieved, however this is + * assuming that the driver did indeed read the data. I believe a better method is to present the data but still return an + * error code leaving it up to the caller to determine what to do with the data (if any.) However in the interest of tweaking + * the kernel as little as possible this mread function was created to return an error. */ + +static int mread(int mtd_fd, void *data_ptr, int data_len) +{ + struct mtd_ecc_stats ecc_stats; + int status, fails; + + ioctl(mtd_fd, ECCGETSTATS, &ecc_stats); + fails = ecc_stats.failed; + + status = read(mtd_fd, data_ptr, data_len); + if (status < 0) + return(status); + + ioctl(mtd_fd, ECCGETSTATS, &ecc_stats); + + if (fails != ecc_stats.failed) + return(-1); + + return(status); +} + + +static int nandReadBlk(mtd_info_t *mtd, int blk_addr, int data_len, + unsigned char *data_ptr, int mtd_fd) +{ + if (lseek(mtd_fd, blk_addr, SEEK_SET) < 0) + { + fprintf(stderr, "ERROR!!! Could not block seek to 0x%x!\n", blk_addr); + return(-1); + } + + if (mread(mtd_fd, data_ptr, data_len) < 0) + { + fprintf(stderr, "ERROR!!! Could not read block at offset 0x%x!\n", blk_addr); + return(-1); + } + + return(0); +} +#else +static int nandReadBlk(mtd_info_t *mtd __attribute__((unused)), + int blk_addr __attribute__((unused)), + int data_len __attribute__((unused)), + unsigned char *data_ptr __attribute__((unused)), + int mtd_fd __attribute__((unused))) +{ + flashutil_debug("mtd=%p, blkaddr=0x%x, len=%d, data=%p, fd=%d", + mtd, blk_addr, data_len, data_ptr, mtd_fd); + return(0); +} +#endif /* DESKTOP_LINUX */ + + +/* Write data, must pass function an aligned block address */ +int nandWriteBlk(mtd_info_t *mtd, int blk_addr, int data_len, unsigned char *data_ptr, int mtd_fd, int write_JFFS2_clean_marker) +{ +#ifndef DESKTOP_LINUX +#if !defined(CONFIG_CPU_BIG_ENDIAN) + const unsigned short jffs2_clean_marker[] = {JFFS2_MAGIC_BITMASK, JFFS2_NODETYPE_CLEANMARKER, 0x0008, 0x0000}; +#else + const unsigned short jffs2_clean_marker[] = {JFFS2_MAGIC_BITMASK, JFFS2_NODETYPE_CLEANMARKER, 0x0000, 0x0008}; +#endif + struct mtd_write_req ops; + int page_addr, byte, sts = 0; + + flashutil_debug("mtd=%p, blkaddr=0x%x, len=%d, data=%p, fd=%d, marker=%d", + mtd, blk_addr, data_len, data_ptr, mtd_fd, write_JFFS2_clean_marker); + + for (page_addr = 0; page_addr < data_len; page_addr += mtd->writesize) + { + memset(&ops, 0x00, sizeof(ops)); + + // check to see if whole page is FFs + for (byte = 0; (byte < (int)mtd->writesize) && ((page_addr + byte) < data_len); byte++) + { + if ( *(unsigned char *)(data_ptr + page_addr + byte) != 0xFF ) + { + ops.start = blk_addr + page_addr; + ops.len = (int) mtd->writesize < (data_len - page_addr) ? mtd->writesize : (unsigned int) data_len - page_addr; + ops.usr_data = (uint64_t)(unsigned long)(data_ptr + page_addr); + break; + } + } + + if (write_JFFS2_clean_marker) + { + ops.mode = MTD_OPS_AUTO_OOB; + ops.usr_oob = (uint64_t)(unsigned long)jffs2_clean_marker; + ops.ooblen = sizeof(jffs2_clean_marker); + write_JFFS2_clean_marker = 0; // write clean marker to first page only + } + + if (ops.len || ops.ooblen) + { + if ((sts = ioctl(mtd_fd, MEMWRITE, &ops)) != 0) + { + break; + } + } + } + + return(sts); +#else + flashutil_print("mtd=%p, blkaddr=0x%x, len=%d, data=%p, fd=%d, marker=%d", + mtd, blk_addr, data_len, data_ptr, mtd_fd, write_JFFS2_clean_marker); + return 0; +#endif +} + +static int nandIsBadBlk(int blk_addr, int mtd_fd) +{ +#ifndef DESKTOP_LINUX + loff_t offset = blk_addr; + + int ret = ioctl(mtd_fd, MEMGETBADBLOCK, &offset); + if ( ret > 0) { + fprintf(stderr, "Bad block at 0x%x\n", blk_addr); + return 1; + } + + if( ret < 0 ) { + /* bad block check not available?? Treat as bad block. We are only dealing with NAND */ + fprintf(stderr, "MTD get bad block failed at 0x%x, ret %d\n", blk_addr, ret); + return 1; + } +#else + flashutil_print("addr=0x%x, fd=%d", blk_addr, mtd_fd); +#endif + return(0); +} + +/* Erase the specified NAND flash block. */ +int nandEraseBlk(mtd_info_t *mtd, int blk_addr, int mtd_fd) +{ +#ifndef DESKTOP_LINUX + erase_info_t erase; + + erase.start = blk_addr; + erase.length = mtd->erasesize; + + if (ioctl(mtd_fd, MEMERASE, &erase) < 0) + { + fprintf(stderr, "Could not erase block\n"); + return(-1); + } + flashutil_debug("mtd=%p, addr=0x%x, fd=%d", mtd, blk_addr, mtd_fd); +#else + flashutil_print("mtd=%p, addr=0x%x, fd=%d", mtd, blk_addr, mtd_fd); +#endif + + return(0); +} + +/* Note: the following functions is for CFEROM flashing debugging. */ +int nandEraseBlk_print(mtd_info_t *mtd, int blk_addr, int mtd_fd) +{ + flashutil_print("mtd=%p, addr=0x%x, fd=%d", mtd, blk_addr, mtd_fd); + return(0); +} + + +/*********************************************************************** + * Function Name: scan_partition + * Description : scans mtd names to determine type + * Returns : None, JFFS2 or (pure) UBI image type + ***********************************************************************/ +int nand_image_type(unsigned char * buf) +{ // scans buffer for image type + int ret = 0; + struct ubi_ec_hdr * ec = (struct ubi_ec_hdr *) buf; + struct jffs2_raw_dirent *pdir = (struct jffs2_raw_dirent *) buf; + + if( nandIsLegacyFlashLayout() ) + { + if(je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK) + ret = JFFS2_IMAGE; + else if(be32_to_cpu(ec->magic) == UBI_EC_HDR_MAGIC) + ret = UBI_IMAGE; + } + else + ret = UBI_IMAGE; + + + return(ret); +} + + +static int scan_partition(char * name) +{ + int i; + int mtd_fd; + mtd_info_t * mtd; + unsigned char buf[4]; + int ret = 0; + + mtd = get_mtd_device_handle(name, &mtd_fd, 0); + + if( !IS_ERR_OR_NULL(mtd) ) + { // Find the partition type + for( i = 0; i < (int)mtd->size; i += mtd->erasesize ) + { + if(IS_ERR(nandReadBlk(mtd, i, 4, buf, mtd_fd))) + continue; + + if ((ret = nand_image_type(buf))) + break; + + } + + put_mtd_device(mtd, mtd_fd, -1); + } + + return(ret); +} + + +#ifndef DESKTOP_LINUX +/*********************************************************************** + * Function Name: findBootBlockInImage + * Description : find the boot code blk number in image buffer + * Returns : number of block boot code takes, -1 if invalid image + ***********************************************************************/ +static int findBootBlockInImage(mtd_info_t *mtd, unsigned char *pImage, unsigned int imageSize) +{ + int i = 0; + int blk_size = mtd->erasesize; + unsigned char* pImageEnd = pImage + imageSize; + + while( (nand_image_type(pImage) != JFFS2_IMAGE) && (nand_image_type(pImage) != UBI_IMAGE) ) + { + i++; + pImage += blk_size; + if( pImage >= pImageEnd ) + { + i = -1; + break; + } + } + + return i; +} + +/*********************************************************************** + * Function Name: available_space_in_partition + * Description : find usable space in mtd partiton + * Returns : number of usable bytes + ***********************************************************************/ +static unsigned int available_space_in_partition(mtd_info_t *mtd, int mtd_fd) +{ + unsigned int total_size = mtd->size; + unsigned int block_size = mtd->erasesize; + unsigned int block_addr, avail_size = total_size; + + for( block_addr = 0; block_addr < total_size; block_addr += block_size ) + { + if( nandIsBadBlk(block_addr, mtd_fd) ) + avail_size -= block_size; + } + + return avail_size; +} + +/*********************************************************************** + * Function Name: checkImageSizeForNand + * Description : check if the image can fit into the target partition + * Returns : 0 if fit and non zero if it does not + ***********************************************************************/ +static int checkImageSizeForNand(mtd_info_t *mtd, int mtd_fd, unsigned char* imagePtr, unsigned int imageSize) +{ + int rc = 0; + int blk_size = mtd->erasesize; + int boot_img_blk, boot_img_size; + unsigned int avail_part_size = available_space_in_partition(mtd, mtd_fd); + unsigned int required_fs_size; + + boot_img_blk = findBootBlockInImage(mtd, imagePtr, imageSize); + if( boot_img_blk < 0 ) + return -1; + boot_img_size = boot_img_blk*blk_size; + required_fs_size = imageSize - boot_img_size + (NAND_CFE_RAM_RSVD_BLK-1)*blk_size; + + if ( avail_part_size < required_fs_size ) { + fprintf(stderr,"\nFS Image(%d) plus reserve(%d) bigger than the partition(%d)\n", imageSize-boot_img_size, (NAND_CFE_RAM_RSVD_BLK-1)*blk_size, avail_part_size); + rc = -1; + } + + return rc; +} +#endif /* DESKTOP_LINUX */ + + +/*********************************************************************** + * Function Name: nandGetBootPartition + * Description : Returns the booted partition + * Returns : boot partition or -1 for failure + ***********************************************************************/ +int nandGetBootPartition(void) +{ + int ret = -1; + +#ifndef DESKTOP_LINUX + FILE *fp = NULL; + char line[COMMAND_LINE_SIZE] = {0}; + char name[MAX_MTD_NAME_SIZE] = {0}; + static int cached_boot_partition = -1; + + if (cached_boot_partition != -1) + { + return cached_boot_partition; + } + + if( nandIsLegacyFlashLayout()) + { + if ( (fp = fopen("/proc/mtd","r")) == 0) + { + fprintf(stderr, "ERROR!!! Could not open /proc/mtd\n"); + return(0); + } + + while(fgets(line, sizeof(line), fp)) + { + sscanf(line, "%*s %*s %*s %s", name); + + if(!strcmp("\"image\"", name)) + { + ret = 1; + break; + } + + if(!strcmp("\"image_update\"", name)) + { + ret = 2; + break; + } + } + fclose(fp); + } + else + { + /* Use get_rootfs_dev script */ +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + fp = popen("/etc/get_rootfs_dev.sh", "r"); +#else + fp = popen("/rom/etc/get_rootfs_dev.sh", "r"); +#endif + if (fp == NULL) { +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + fprintf(stderr, "Failed to run /etc/get_rootfs_dev.sh command\n" ); +#else + fprintf(stderr, "Failed to run /rom/etc/get_rootfs_dev.sh command\n" ); +#endif + return 0; + } + + if(fgets(line, sizeof(line), fp)) + { + if( strstr(line, "ubiblock")) + { + sscanf(line,"/dev/ubiblock0_" "%d", &ret); + /* Translate from volume id to image number */ + //FIXME: Magic numbers + ret = (ret==4?1:2); + } + else + { + sscanf(line,"ubi:rootfs" "%d", &ret); + } + } + pclose(fp); + } + + cached_boot_partition = ret; +#endif /* DESKTOP_LINUX */ + + return(ret); +} + + +unsigned int nvramDataOffset(const mtd_info_t * mtd __attribute__((unused))) +{ + return( (NVRAM_DATA_REL_OFFSET+(IMAGE_OFFSET-(IMAGE_OFFSET/((unsigned int)mtd->erasesize))*((unsigned int)mtd->erasesize))) ); +} + + +static unsigned int nvramSector(const mtd_info_t * mtd __attribute__((unused))) +{ + return( (IMAGE_OFFSET/((unsigned int)mtd->erasesize)) ); +} + + +#ifndef DESKTOP_LINUX +#define MAX_NVRAM_MIRROR_LOOKUP_OFFSET 20*1024*1024 + + + +int nvRamMirrorSearch( PNVRAM_DATA nv) +{ + mtd_info_t * mtd; + int mtd_fd; + int search_complete=0; + unsigned char *buff=NULL; + loff_t offset=0; + + + if ( (mtd = get_mtd_device_handle("nvram", &mtd_fd, 0)) == 0) + { + fprintf(stderr, "ERROR!!! Could not open nvram partition!\n"); + search_complete=-1; + } + if (lseek(mtd_fd, 0, SEEK_SET) < 0) + { + fprintf(stderr, "ERROR!!! Could not seek to 0\n"); + search_complete=-1; + } + //buff=malloc(sizeof(NVRAM_DATA)+strlen(NVRAM_DATA_SIGN)); + buff=malloc(2048); + if(buff == NULL) + { + fprintf(stderr, "ERROR!!! memory allocation failed\n"); + search_complete=-1; + } + + + for(offset=0;search_complete == 0 && offset < MAX_NVRAM_MIRROR_LOOKUP_OFFSET;offset += 2048) { + memset(buff, '\0', 2048); + if(mread(mtd_fd, buff, 2048) < 0) + { + fprintf(stderr, "ERROR!!! Cound not get NVRAM data!\n"); + } + else + { + if(offset%mtd->erasesize == 0) { + if(check_jffs_ubi_magic(buff) == 1) { + printf("NVRAM_MIRROR SCAN: OFFSET blk [%" PRIx64 "] \n", offset); + search_complete = 2; + continue; + } + } + ; + //check nvram data signature + if(is_nvram_offset(buff, 0, 1, NULL, NULL) == IMG_NVRAM) { + memcpy(nv, buff+strlen(NVRAM_DATA_SIGN), sizeof(NVRAM_DATA)); + search_complete = 1; + break; + } + } + } + put_mtd_device(mtd, mtd_fd, -1); + return search_complete; +} +#endif + + +/** read the nvramData struct from the in-memory copy of nvram. + * The caller is not required to have flashImageMutex when calling this + * function. However, if the caller is doing a read-modify-write of + * the nvram data, then the caller must hold flashImageMutex. This function + * does not know what the caller is going to do with this data, so it + * cannot assert flashImageMutex held or not when this function is called. + * + * @return pointer to NVRAM_DATA buffer which the caller must free + * or NULL if there was an error + */ +int nandReadNvramData(void *nvramData) +{ +#ifndef DESKTOP_LINUX + uint32_t crc = CRC_INITIAL_VALUE, savedCrc; + mtd_info_t * mtd; + int mtd_fd; + int status = 0; + NVRAM_DATA *pNvramData = (NVRAM_DATA*)nvramData; + + if ( (mtd = get_mtd_device_handle("nvram", &mtd_fd, 0)) == 0) + { + fprintf(stderr, "ERROR!!! Could not open nvram partition!\n"); + return(0); + } + + if (lseek(mtd_fd, nvramDataOffset(mtd), SEEK_SET) < 0) + { + fprintf(stderr, "ERROR!!! Could not seek to 0x%x in nvram partition!\n", nvramDataOffset(mtd)); + } + else if (mread(mtd_fd, pNvramData, sizeof(NVRAM_DATA)) < 0) + { + fprintf(stderr, "ERROR!!! Cound not get NVRAM data!\n"); + } + + put_mtd_device(mtd, mtd_fd, -1); + + savedCrc = pNvramData->ulCheckSum; + pNvramData->ulCheckSum = 0; + crc = genUtl_getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc); + if (savedCrc == crc) + { + // this can happen if we write a new cfe image into flash. + // The new image will have an invalid nvram section which will + // get updated to the inMemNvramData. We detect it here and + // commonImageWrite will restore previous copy of nvram data. + //kfree(pNvramData); + status = 1; + } + else + { + status=nvRamMirrorSearch(pNvramData); + } + + return(status); +#else + flashutil_print("readNvramData(%p)", nvramData); + return 1; +#endif +} + +// mtd block access functions +static unsigned int read_blk(unsigned char * start __attribute__((unused)), unsigned int block, unsigned int offset, unsigned int blk_size, unsigned char * buf, unsigned int amount, void * mtd, int mtd_fd) +{ + return(nandReadBlk((mtd_info_t *)mtd, ((block * blk_size) + offset), amount, buf + offset, mtd_fd)+1); +} + + +static unsigned int write_blk(unsigned char * start __attribute__((unused)), unsigned int block, unsigned int offset, unsigned int blk_size, unsigned char * buf, unsigned int amount, void * mtd, int mtd_fd) +{ + return(nandWriteBlk((mtd_info_t *)mtd, ((block * blk_size) + offset), amount, buf + offset, mtd_fd, 0)+1); +} + + +static unsigned int erase_blk(unsigned int block, unsigned int blk_size, void * mtd, int mtd_fd) +{ + return(nandEraseBlk((mtd_info_t *)mtd, (block * blk_size), mtd_fd)+1); +} + + +// UBI block access functions +#ifndef DESKTOP_LINUX +static unsigned int read_block(unsigned char * start __attribute__((unused)), unsigned int block, unsigned int offset, unsigned int blk_size, unsigned char * buf, unsigned int amount, void * mtd, int mtd_fd) +{ +// FILE *fp = fopen("/dev/mtdblock9","r"); // two ways could do this, either with file pointer or file descriptor + +// if (fseek(fp, (block * blk_size) + offset, SEEK_SET) < 0) + if (lseek(mtd_fd, (block * blk_size) + offset, SEEK_SET) < 0) + return(0); + +// if (fread(buf, amount, 1, fp) < 0) + if (mread(mtd_fd, buf, amount) < 0) + return(0); + +// fclose(fp); + return(amount); +} + + +static unsigned int write_block(unsigned char * start __attribute__((unused)), unsigned int block, unsigned int offset, unsigned int blk_size, unsigned char * buf, unsigned int amount, void * mtd, int mtd_fd) +{ +// FILE *fp = fopen("/dev/mtdblock9","w"); // two ways could do this, either with file pointer or file descriptor + +// if (fseek(fp, (block * blk_size) + offset, SEEK_SET) < 0) + if (lseek(mtd_fd, (block * blk_size) + offset, SEEK_SET) < 0) + return(0); + +// if (fwrite(buf, amount, 1, fp) < 0) + if (write(mtd_fd, buf, amount) < 0) + return(0); + +// fclose(fp); + return(amount); +} + + +#else +static unsigned int read_block(unsigned char * start __attribute__((unused)), unsigned int block __attribute__((unused)), unsigned int offset __attribute__((unused)), unsigned int blk_size __attribute__((unused)), unsigned char * buf __attribute__((unused)), unsigned int amount __attribute__((unused)), void * mtd __attribute__((unused)), int mtd_fd __attribute__((unused))) +{ + return(0); +} + +static unsigned int write_block(unsigned char * start __attribute__((unused)), unsigned int block __attribute__((unused)), unsigned int offset __attribute__((unused)), unsigned int blk_size __attribute__((unused)), unsigned char * buf __attribute__((unused)), unsigned int amount __attribute__((unused)), void * mtd __attribute__((unused)), int mtd_fd __attribute__((unused))) +{ + return(0); +} +#endif + + +int nandGetSequenceNumber(int imageNumber) +{ /* NAND Flash */ +#ifndef DESKTOP_LINUX + int seqNumber = -1; +#else + int seqNumber = imageNumber; +#endif /* DESKTOP_LINUX */ + FILE *fp; + unsigned char * buf = NULL; + char fname[] = NAND_CFE_RAM_NAME; + int i, type, partitionIsBootedPartition = (nandGetBootPartition() == imageNumber); + + /* first check if we already have the number in cache */ + if (imageNumber == 1) + fp = fopen("/tmp/seqNumFirstImg", "r"); + else + fp = fopen("/tmp/seqNumSecondImg", "r"); + + if (fp != NULL) + { + int status; + + status = fread(&seqNumber, sizeof(seqNumber), 1, fp); + fclose(fp); + + if (status == 1) + { + return(seqNumber); + } + } + + if( !nandIsLegacyFlashLayout() ) + { + if (getImgSeqNum(imageNumber, &seqNumber)) + printf("%s: Error! Could not retrieve sequence number for image %d\n", __FUNCTION__, imageNumber); + return seqNumber; + } + + if (partitionIsBootedPartition) + { // scan mtd device names + if (exist_mtd_dev_nm("METADATA") || exist_mtd_dev_nm("METADATACOPY")) + type = UBI_IMAGE; + else + type = JFFS2_IMAGE; + } + else // get from non-booted image + type = scan_partition("image_update"); + + /* If full secure boot is in play, the CFE RAM file is the encrypted version */ + if (type == JFFS2_IMAGE) + { + if (otp_is_boot_secure()) + strcpy(fname, NAND_CFE_RAM_SECBT_NAME); + else + { + if (otp_is_boot_mfg_secure()) + strcpy(fname, NAND_CFE_RAM_SECBT_MFG_NAME); + } + } + + // Find the directory entry. + if (type == JFFS2_IMAGE) + { + char cferam_buf[32], cferam_fmt[32]; + int rc; + + if (!partitionIsBootedPartition) + { + strcpy(cferam_fmt, "/tmp/mnt/"); + rc = system("mkdir /tmp/mnt"); + + if( !IS_ERR_OR_NULL(exist_mtd_dev_nm("bootfs_update")) ) // check if JFFS2 with UBIFS + { // JFFS2 with UBIFS + rc = system("mount -t jffs2 mtd:bootfs_update /tmp/mnt -r"); + } + else + { // JFFS2 only + rc = system("mount -t jffs2 mtd:rootfs_update /tmp/mnt -r"); + } + + if (rc < 0) + { + fprintf(stderr, "ERROR!!! mount command failed!\n"); + return(seqNumber); + } + } + else + { // get from current booted image + if( !IS_ERR_OR_NULL(exist_mtd_dev_nm("bootfs")) ) + { // JFFS2 with UBIFS + strcpy(cferam_fmt, "/bootfs/"); + } + else + { // JFFS2 only + strcpy(cferam_fmt, "/"); + } + } + + /* Find the sequence number of the specified partition. */ + fname[strlen(fname) - 3] = '\0'; /* remove last three chars */ + strcat(cferam_fmt, fname); + strcat(cferam_fmt, "%3.3d"); + + for( i = 0; i < 1000; i++ ) + { + sprintf(cferam_buf, cferam_fmt, i); + fp = fopen(cferam_buf, "r"); + if (fp != NULL) + { + fclose(fp); + + /* Seqence number found. */ + seqNumber = i; + break; + } + } + + if( !partitionIsBootedPartition ) + { + if (system("umount /tmp/mnt") < 0) + { + fprintf(stderr, "ERROR!!! umount command failed!\n"); + } + } + } + + if (type == UBI_IMAGE) + { + int mtd_fd; + mtd_info_t * mtd; + char imageSequence[3]; + unsigned int len; + + if (partitionIsBootedPartition) + { // use UBI interface + int mtdblock_fd; + + for (i = 0; i < 2; i++) + { + mtd = get_mtd_device_handle(i ? "METADATACOPY" : "METADATA", &mtd_fd, &mtdblock_fd); + + if ( IS_ERR_OR_NULL(mtd) ) + { + fprintf(stderr, "ERROR!!! unable to open mtd partition %s\n", i ? "METADATACOPY" : "METADATA"); + continue; + } + + len = mtd->erasesize; + + if ( !buf && ((buf = malloc(len)) == 0) ) + { + fprintf(stderr, "ERROR!!! cannot allocate block memory for buffer\n"); + put_mtd_device(mtd, mtd_fd, mtdblock_fd); + continue; + } + + if (parse_ubi(0, buf, 0, mtd->size / len, len, -1, fname, imageSequence, 0, 0, read_block, 0, 0, mtd, mtdblock_fd) == 3) + { + seqNumber = ((imageSequence[0] - '0') * 100) + ((imageSequence[1] - '0') * 10) + (imageSequence[2] - '0'); + put_mtd_device(mtd, mtd_fd, mtdblock_fd); + + break; + } + else + printf("ERROR!!! Could not find %s partition image metadata volume %d\n", (imageNumber == 1) ? "first" : "second", i); + + put_mtd_device(mtd, mtd_fd, mtdblock_fd); + } + + if (buf) + free(buf); + } + else + { // use mtd interface + mtd = get_mtd_device_handle("image_update", &mtd_fd, 0); + + if ( IS_ERR_OR_NULL(mtd) ) + { + fprintf(stderr, "ERROR!!! unable to open image %d\n", imageNumber); + return(seqNumber); + } + + len = mtd->erasesize; + + if ((buf = malloc(len)) == 0) + { + fprintf(stderr, "ERROR!!! cannot allocate block memory for buffer\n"); + put_mtd_device(mtd, mtd_fd, -1); + return(seqNumber); + } + + for (i = 0; i < 2; i++) + { + if (parse_ubi(0, buf, 0, mtd->size / len, len, i ? VOLID_METADATA_COPY : VOLID_METADATA, fname, imageSequence, 0, 0, read_blk, 0, 0, mtd, mtd_fd) == 3) + { + seqNumber = ((imageSequence[0] - '0') * 100) + ((imageSequence[1] - '0') * 10) + (imageSequence[2] - '0'); + break; + } + } + + free(buf); + put_mtd_device(mtd, mtd_fd, -1); + } + } + + if (seqNumber != -1) + { + FILE *fp; + + if (imageNumber == 1) + fp = fopen("/tmp/seqNumFirstImg", "w"); + else + fp = fopen("/tmp/seqNumSecondImg", "w"); + + if (fp != NULL) + { + fwrite(&seqNumber, sizeof(seqNumber), 1, fp); + fclose(fp); + } + } + + return(seqNumber); +} + + +static unsigned int readBlk(unsigned char * start, unsigned int block, + unsigned int offset, unsigned int blk_size, unsigned char * buf, + unsigned int amount, void * mtd __attribute__((unused)), + int mtd_fd __attribute__((unused))) +{ + memcpy(buf + offset, start + (block * blk_size) + offset, amount); + return(amount); +} + +static unsigned int writeBlk(unsigned char * start, unsigned int block, + unsigned int offset, unsigned int blk_size, unsigned char * buf, + unsigned int amount, void * mtd __attribute__((unused)), + int mtd_fd __attribute__((unused))) +{ + memcpy(start + (block * blk_size) + offset, buf + offset, amount); + return(amount); +} + +/* + * nandUpdateSeqNum + * + * Read the sequence number from rootfs partition only. The sequence number is + * the extension on the cferam file. Add one to the sequence number + * and change the extenstion of the cferam in the image to be flashed to that + * number. + */ +unsigned char *nandUpdateSeqNum(unsigned char *imagePtr, int imageSize, int blkLen, int seq, int *found) +{ + char fname[] = NAND_CFE_RAM_NAME; + int fname_actual_len = strlen(fname); + int fname_cmp_len = strlen(fname) - 3; /* last three are digits */ + char * ret = NULL; + + /* If full secure boot is in play, the CFE RAM file is the encrypted version */ + if (nand_image_type(imagePtr) == JFFS2_IMAGE) + { + if (otp_is_boot_secure()) + strcpy(fname, NAND_CFE_RAM_SECBT_NAME); + else + { + if (otp_is_boot_mfg_secure()) + strcpy(fname, NAND_CFE_RAM_SECBT_MFG_NAME); + } + } + + if (seq == -1) + seq = nandGetSequenceNumber(nandGetBootPartition()); // get sequence number of booted partition + + if( !nandIsLegacyFlashLayout() ) + { + seq = (seq + 1) % 999; // set newly written image sequence number one greater than other image + setImgSeqNum(nandGetBootPartition() == 1 ? 2 : 1, seq); + + return((unsigned char *)ret); + } + + if( seq != -1 ) + { + unsigned char *buf, *p; + struct jffs2_raw_dirent *pdir; + struct ubi_ec_hdr *ec; + unsigned long version = 0; + int done = 0; + unsigned int type = 0; // image type + + while (!nand_image_type(imagePtr) && (imageSize > 0)) + { + imagePtr += blkLen; + imageSize -= blkLen; + } + + /* Confirm that we did find a JFFS2_MAGIC_BITMASK or UBIFS magic number. If not, we are done */ + if (imageSize <= 0) + { + done = 1; + } + + /* Increment the new highest sequence number. Add it to the CFE RAM + * file name. + */ + seq++; + if (seq > 999) + { + seq = 0; + } + + /* Search the image and replace the last three characters of file + * cferam.000 with the new sequence number. + */ + for(p = imagePtr; p < imagePtr+imageSize && done == 0; p += blkLen) + { + ec = (struct ubi_ec_hdr *) p; + + if( (nand_image_type(p) == UBI_IMAGE) && (genUtl_getCrc32((void *)ec, UBI_EC_HDR_SIZE-4, CRC_INITIAL_VALUE) == be32_to_cpu(ec->hdr_crc)) ) + { // will only need to spin through the blocks once since the image is built with volumes in order + + unsigned char * buffer; + char seqstr[3] = {(seq / 100) + '0', ((seq % 100) / 10) + '0', ((seq % 100) % 10) + '0'}; + int i, try; + + if (!(buffer = (unsigned char *) malloc(blkLen))) + return(0); + + for (i = 0; i < 2; i++) + { + if (i) + try = VOLID_METADATA_COPY; + else + try = VOLID_METADATA; + + if (parse_ubi((unsigned char *)imagePtr, buffer, (p - imagePtr) / blkLen, imageSize / blkLen, blkLen, try, fname, seqstr, &ret, 0, readBlk, writeBlk, 0, 0, 0) == 3) + { + printf("\nUpdating pureUBI metadata %d sequence number to %d", i, seq); + (*found)++; + } + } + + free(buffer); + + done = 1; + } + else + { + if (!type) + type = JFFS2_IMAGE; + + buf = p; + while( buf < (p + blkLen) ) + { + pdir = (struct jffs2_raw_dirent *) buf; + if( nand_image_type(buf) == JFFS2_IMAGE ) + { + if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT && + fname_actual_len == pdir->nsize && + !memcmp(fname, pdir->name, fname_cmp_len) && + je32_to_cpu(pdir->version) > version && + je32_to_cpu(pdir->ino) != 0 ) + { + printf("Updating JFFS2 sequence number to %d\n", seq); + /* File cferam.000 found. Change the extension to the + * new sequence number and recalculate file name CRC. + */ + buf = (unsigned char *)pdir->name + fname_cmp_len; + buf[0] = (seq / 100) + '0'; + buf[1] = ((seq % 100) / 10) + '0'; + buf[2] = ((seq % 100) % 10) + '0'; + buf[3] = '\0'; + + je32_to_cpu(pdir->name_crc) = genUtl_getCrc32(pdir->name, (uint32_t)fname_actual_len, 0); + + version = je32_to_cpu(pdir->version); + + /* Setting 'done = 1' assumes there is only one version + * of the directory entry. + */ + done = 1; + ret = (char *)p; /* Pointer to the block containing CFERAM directory entry in the image to be flashed last to finalize image */ + (*found)++; + break; + } + + buf += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + } + else + { + done = 1; + break; + } + } + } + } + } + + if (seq != -1) + { // update image_update sequence number for the image that is to be written + FILE *fp; + + if(nandGetBootPartition() == 1) + fp = fopen("/tmp/seqNumSecondImg", "w"); + else + fp = fopen("/tmp/seqNumFirstImg", "w"); + + if (fp != NULL) + { + fwrite(&seq, sizeof(seq), 1, fp); + fclose(fp); + } + } + + return((unsigned char *)ret); +} + + +static int get_image_version( uint8_t *imagePtr, int imageSize, int erasesize, char *image_name, int image_name_len ) +{ + int type; + unsigned char *buf, *p; + char fname[] = IMAGE_VERSION_FILE_NAME; + int fname_len = strlen(fname); + struct jffs2_raw_dirent *pdir; + struct jffs2_raw_inode *pino; + unsigned long version = 0; + jint32_t ino; + int ret = -1; + + while (imageSize > 0) + { + type = nand_image_type(imagePtr); + if ((type == JFFS2_IMAGE) || (type == UBI_IMAGE)) + break; + + imagePtr += erasesize; + imageSize -= erasesize; + } + + /* Confirm that we did find a magic bitmask. If not, we are done */ + if (imageSize <= 0) + { + return -1; + } + + if (type == JFFS2_IMAGE) + { + for(buf = imagePtr; buf < imagePtr+imageSize; buf += 4) + { + p = buf; + while( p < buf + erasesize ) + { + pdir = (struct jffs2_raw_dirent *) p; + if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK && + je32_to_cpu(pdir->hdr_crc) == genUtl_getCrc32(p, + sizeof(struct jffs2_unknown_node) - 4, 0) ) + { + if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT) + { + + if( + fname_len == pdir->nsize && + !memcmp(fname, pdir->name, fname_len) && + je32_to_cpu(pdir->version) > version && + je32_to_cpu(pdir->ino) != 0 ) + { + ino.v32=je32_to_cpu(pdir->ino); + je32_to_cpu(pdir->name_crc) = genUtl_getCrc32(pdir->name, + (unsigned long) fname_len, 0); + version = je32_to_cpu(pdir->version); + p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + pino = (struct jffs2_raw_inode *) p; + if( je16_to_cpu(pino->magic) == JFFS2_MAGIC_BITMASK ) + { + if(je16_to_cpu(pino->nodetype)==JFFS2_NODETYPE_INODE && + je32_to_cpu(pino->ino) == ino.v32) + { + if(image_name != NULL) + { + memcpy(image_name, pino->data, (int)pino->dsize.v32 > image_name_len ? image_name_len : (int)pino->dsize.v32); + return 0; + } + else + break; + } + } + } + } + p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03; + } + else + break; + } + } + } + + for(buf = imagePtr; (buf < imagePtr+imageSize) && (ret == -1); buf++) + { // search whole image for version string + if (!memcmp(buf, IDENT_TAG, strlen(IDENT_TAG))) + { + unsigned char * start; + int size = 0; + + buf += 20; + start = buf; + + while ((*buf >= ' ') && (*buf <= '~') && (buf < imagePtr+imageSize) && (size < 128)) + { + if (!memcmp(buf, " $\n", 3)) + { // found terminator, done + memcpy(image_name, start, size); + image_name[size] = 0; + ret = 0; + break; + } + + buf++; + size++; + } + } + } + + return(ret); +} + +#ifndef DESKTOP_LINUX +// NAND flash bcm image +// return: +// 0 - ok +// !0 - the sector number fail to be flashed (should not be 0) +static int bcmNandImageSet( char *rootfs_part, unsigned char *image_ptr, int img_size, NVRAM_DATA * inMemNvramData_buf) +{ + int sts = -1; + int blk_addr; + unsigned char *cferam_ptr; + int cferam_found = 0; + int rsrvd_for_cferam; + unsigned char *end_ptr = image_ptr + img_size; + int mtd0_fd; + mtd_info_t * mtd0 = get_mtd_device_handle("image", &mtd0_fd, 0); + WFI_TAG wt = {0,0,0,0,0}; + int nvramXferSize; + + uint32_t btrmEnabled = otp_is_btrm_boot(); + + if( !nandIsLegacyFlashLayout() ) + { + printf("%s: WARNING:Function not implemented for new flash layout\n", __FUNCTION__); + return 0; + } + + /* Reserve room to flash block containing directory entry for CFERAM. */ + rsrvd_for_cferam = NAND_CFE_RAM_RSVD_BLK * mtd0->erasesize; + + if( !IS_ERR_OR_NULL(mtd0) ) + { + unsigned int chip_id; + chip_id = get_chip_id(); + + int blksize = mtd0->erasesize / 1024; + + memcpy(&wt, end_ptr, sizeof(wt)); + +#if defined(CHIP_FAMILY_ID_HEX) + chip_id = CHIP_FAMILY_ID_HEX; +#endif + if( (wt.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + wt.wfiChipId != chip_id ) + { + int id_ok = 0; + + if (id_ok == 0) { + fprintf(stderr, "Chip Id error. Image Chip Id = %x, Board Chip Id = " + "%x\n", wt.wfiChipId, chip_id); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } + else if( wt.wfiFlashType == WFI_NOR_FLASH ) + { + fprintf(stderr, "\nERROR: Image does not support a NAND flash device.\n\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + else if( (wt.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + ((wt.wfiFlashType < WFI_NANDTYPE_FLASH_MIN && wt.wfiFlashType > WFI_NANDTYPE_FLASH_MAX) || + blksize != WFI_NANDTYPE_TO_BKSIZE(wt.wfiFlashType) ) ) + { + fprintf(stderr, "\nERROR: NAND flash block size %dKB does not work with an " + "image built with %dKB block size\n\n", blksize,WFI_NANDTYPE_TO_BKSIZE(wt.wfiFlashType)); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + else if ( (get_flash_type() != FLASH_IFC_SPINAND) && + ((( (wt.wfiFlags & WFI_FLAG_SUPPORTS_BTRM)) && (! btrmEnabled)) || + ((! (wt.wfiFlags & WFI_FLAG_SUPPORTS_BTRM)) && ( btrmEnabled))) ) + { + fprintf(stderr, "The image type does not match the OTP configuration of the SoC. Aborting.\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + else + { + put_mtd_device(mtd0, mtd0_fd, -1); + mtd0 = get_mtd_device_handle(rootfs_part, &mtd0_fd, 0); + + if( IS_ERR_OR_NULL(mtd0) ) + { + fprintf(stderr, "ERROR!!! Could not access MTD partition %s\n", rootfs_part); + return -1; + } + + if( mtd0->size == 0LL ) + { + fprintf(stderr, "ERROR!!! Flash device is configured to use only one file system!\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } + } + + if( !IS_ERR_OR_NULL(mtd0) ) + { + int ofs; + int writelen; + int writing_ubifs; + + if( checkImageSizeForNand(mtd0, mtd0_fd, image_ptr, img_size) ) + { + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + + if( nand_image_type(image_ptr) ) + { /* Downloaded image does not contain CFE ROM boot loader */ + ofs = 0; + } + else + { + /* Downloaded image contains CFE ROM boot loader. */ + PNVRAM_DATA pnd = (PNVRAM_DATA) (image_ptr + nvramSector(mtd0) * ((unsigned int)mtd0->writesize) + nvramDataOffset(mtd0)); + + if( verifyImageDDRType(wt.wfiFlags, inMemNvramData_buf) != 0 ) { + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + + ofs = mtd0->erasesize; +#if defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148) || defined(CONFIG_BCM94908) || defined(BCM_XRDP) +#if defined(CONFIG_BCM94908) + // if we are flashing a NAND device with CFEROM image + if(get_flash_type() == FLASH_IFC_NAND ) { + if(nand_image_type(image_ptr) == 0) + { + int remain = IMAGE_OFFSET%mtd0->erasesize; + memset(image_ptr, '\0', remain); + } + } + else if(get_flash_type() != FLASH_IFC_SPINAND) { +#endif + /* check if it is zero padded for backward compatiblity */ + if( (wt.wfiFlags&WFI_FLAG_HAS_PMC) == 0 ) + { + unsigned int *pImg = (unsigned int *)image_ptr; + unsigned char * pBuf = (unsigned char *)image_ptr; + int block_start, block_end, remain, block; + mtd_info_t *mtd1; + int mtd1_fd; + + if( *pImg == 0 && *(pImg+1) == 0 && *(pImg+2) == 0 && *(pImg+3) == 0 ) + { + /* the first 64KB are for PMC in 631x8, need to preserve that for cfe/linux image update if it is not for PMC image update. */ + block_start = 0; + block_end = IMAGE_OFFSET/mtd0->erasesize; + remain = IMAGE_OFFSET%mtd0->erasesize; + + mtd1 = get_mtd_device_handle("nvram", &mtd1_fd, 0); + if( !IS_ERR_OR_NULL(mtd1) ) + { + for( block = block_start; block < block_end; block++ ) + { + nandReadBlk(mtd1, block*mtd1->erasesize, mtd1->erasesize, pBuf, mtd1_fd); + pBuf += mtd1->erasesize; + } + + if( remain ) + { + block = block_end; + nandReadBlk(mtd1, block*mtd1->erasesize, remain, pBuf, mtd1_fd); + } + + put_mtd_device(mtd1, mtd1_fd, -1); + } + else + { + fprintf(stderr, "Failed to get nvram mtd device\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } + else + { + fprintf(stderr, "Invalid NAND image.No PMC image or padding\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } +#if defined(CONFIG_BCM94908) + } +#endif +#endif + + nvramXferSize = sizeof(NVRAM_DATA); + /* Copy NVRAM data to block to be flashed so it is preserved. */ + memcpy((unsigned char *) pnd, inMemNvramData_buf, nvramXferSize); + + /* Recalculate the nvramData CRC. */ + pnd->ulCheckSum = 0; + pnd->ulCheckSum = genUtl_getCrc32((unsigned char *)pnd, sizeof(NVRAM_DATA), CRC32_INIT_VALUE); + } + + /* + * Scan downloaded image for cferam.000 directory entry and change file extension + * to cfe.YYY where YYY is the current cfe.XXX + 1. If full secure boot is in play, + * the file to be updated is secram.000 and not cferam.000 + */ + cferam_ptr = nandUpdateSeqNum(image_ptr, img_size, mtd0->erasesize, -1, &cferam_found); + + if( (cferam_ptr == NULL) || !cferam_found) + { + fprintf(stderr, "\nERROR: Invalid image. ram.000 not found.\n\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + +#if defined(BCM_PON) || defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148) || defined(CONFIG_BCM94908) || defined(CONFIG_BCM963158) + if ((wt.wfiFlags & WFI_FLAG_SUPPORTS_BTRM) && (ofs != 0)) + { + /* These targets support bootrom boots which is currently enabled. the "nvram" */ + /* mtd device may be bigger than just the first nand block. Check that the new */ + /* image plays nicely with the current partition table settings. */ + int mtd1_fd; + mtd_info_t *mtd1 = get_mtd_device_handle("nvram", &mtd1_fd, 0); + if( !IS_ERR_OR_NULL(mtd1) ) + { + uint32_t *pHdr = (uint32_t *)image_ptr; + pHdr += (mtd1->erasesize / 4); /* pHdr points to the top of the 2nd nand block */ + for( blk_addr = mtd1->erasesize; blk_addr < (int) mtd1->size; blk_addr += mtd1->erasesize ) + { + /* If we are inside the for() loop, "nvram" mtd is larger than 1 block */ + pHdr += (mtd1->erasesize / 4); + } + + if ( !nand_image_type((unsigned char *)pHdr) ) + { + fprintf(stderr, "New sw image does not match the partition table. Aborting.\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + put_mtd_device(mtd1, mtd1_fd, -1); + return -1; + } + put_mtd_device(mtd1, mtd1_fd, -1); + } + else + { + fprintf(stderr, "Failed to get nvram mtd device\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } +#endif + + { // try to make sure we have enough memory to program the image + char * temp; + FILE *fp; + int status = -ENOMEM; + + if ( (fp = fopen("/proc/sys/vm/drop_caches","w")) != NULL ) + { // clear the caches + fwrite("3\n", sizeof(char), 2, fp); + fclose(fp); + } + + if ( (temp = calloc(mtd0->erasesize, sizeof(char))) != NULL ) + { + status = (mread(mtd0_fd, temp, mtd0->erasesize)); + free(temp); + } + + if ((temp == NULL) || (status == -ENOMEM)) + { + fprintf(stderr, "Failed to allocate memory, aborting image write!!!\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } + + if( 0 != ofs ) /* Image contains CFE ROM boot loader. */ + { + /* Prepare to flash the CFE ROM boot loader. */ + int mtd1_fd; + mtd_info_t *mtd1 = get_mtd_device_handle("nvram", &mtd1_fd, 0); + + if( !IS_ERR_OR_NULL(mtd1) ) + { + int iterations = 10; + int status = -1; + + while(iterations--) + { + if (nandEraseBlk(mtd1, 0, mtd1_fd) == 0) + { + if ((status = nandWriteBlk(mtd1, 0, mtd1->erasesize, image_ptr, mtd1_fd, 1)) == 0) + break; + + printf("ERROR WRITING CFE ROM BLOCK!!!\n"); + } + } + + if (status) + { + printf("Failed to write CFEROM, quitting\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + put_mtd_device(mtd1, mtd1_fd, -1); + return -1; + } + + image_ptr += ofs; + +#if defined(BCM_PON) || defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148) || defined(CONFIG_BCM94908) || defined(CONFIG_BCM963158) + if (wt.wfiFlags & WFI_FLAG_SUPPORTS_BTRM) + { + /* We have already checked that the new sw image matches the partition table. Therefore */ + /* burn the rest of the "nvram" mtd (if any) */ + for( blk_addr = mtd1->erasesize; blk_addr < (int) mtd1->size; blk_addr += mtd1->erasesize ) + { + if (nandEraseBlk(mtd1, blk_addr, mtd1_fd) == 0) + { + if (nandWriteBlk(mtd1, blk_addr, mtd1->erasesize, image_ptr, mtd1_fd, 1) != 0) + printf("ERROR WRITING BLOCK!!! at address 0x%x wihin NAND partition nvram\n", blk_addr); + + image_ptr += ofs; + } + } + } +#endif + + put_mtd_device(mtd1, mtd1_fd, -1); + } + else + { + fprintf(stderr, "Failed to get nvram mtd device!!!\n"); + put_mtd_device(mtd0, mtd0_fd, -1); + return -1; + } + } + + /* Erase blocks containing directory entry for CFERAM before flashing the image. */ + for( blk_addr = 0; blk_addr < rsrvd_for_cferam; blk_addr += mtd0->erasesize ) + { + nandEraseBlk(mtd0, blk_addr, mtd0_fd); + } + + /* Flash the image except for CFERAM directory entry, during which all the blocks in the partition (other than CFE) will be erased */ + writing_ubifs = 0; + for( blk_addr = rsrvd_for_cferam; blk_addr < (int) mtd0->size; blk_addr += mtd0->erasesize ) + { + printf("."); + + if (nandEraseBlk(mtd0, blk_addr, mtd0_fd) == 0) + { // block was erased successfully, no need to put clean marker in a block we are writing JFFS2 data to but we do it for backward compatibility + if ( image_ptr == cferam_ptr ) + { // skip CFERAM directory entry block and back the block pointer up a block + image_ptr += mtd0->erasesize; + blk_addr -= mtd0->erasesize; + } + else + { /* Write a block of the image to flash. */ + if( image_ptr < end_ptr ) + { // if any data left, prepare to write it out + writelen = ((image_ptr + mtd0->erasesize) <= end_ptr) + ? (int) mtd0->erasesize : (int) (end_ptr - image_ptr); + } + else + writelen = 0; + + if (writelen) /* Write data with or without JFFS2 clean marker */ + { + if (nandWriteBlk(mtd0, blk_addr, writelen, image_ptr, mtd0_fd, !writing_ubifs) != 0 ) + { + printf("Error writing Block 0x%8.8x, skipping\n", blk_addr); + } + else + { // successful write, increment counter and check for UBIFS split marker if data was written + image_ptr += writelen; + + if (!strncmp(BCM_BCMFS_TAG, (char *)image_ptr - 0x100, strlen(BCM_BCMFS_TAG))) + { + if (!strncmp(BCM_BCMFS_TYPE_UBIFS, (char *)image_ptr - 0x100 + strlen(BCM_BCMFS_TAG), strlen(BCM_BCMFS_TYPE_UBIFS))) + { // check for UBIFS split marker + writing_ubifs = 1; + printf("U"); + } + } + } + } + } + } + fflush(stdout); + } + + printf("\n\n"); + + sts = flashCferam(mtd0, mtd0_fd, rsrvd_for_cferam, cferam_ptr, 0); + + if( sts ) + { + /* + * Even though we try to recover here, this is really bad because + * we have stopped the other CPU and we cannot restart it. So we + * really should try hard to make sure flash writes will never fail. + */ + printf("nandWriteBlk: write failed at blk=%d\n", blk_addr); + sts = (blk_addr > (int) mtd0->erasesize) ? blk_addr / mtd0->erasesize : 1; + } + } + + if( !IS_ERR_OR_NULL(mtd0) ) + { + put_mtd_device(mtd0, mtd0_fd, -1); + } + + return sts; +} +#endif /* DESKTOP_LINUX */ + + +#ifdef DESKTOP_LINUX +int writeImageToNand( unsigned char *string __attribute__((unused)), int size __attribute__((unused))) +{ + return SUCCESS; +} +#else /* DESKTOP_LINUX */ +int writeImageToNand( unsigned char *string, int size ) +{ + NVRAM_DATA * pNvramData; + int ret = SUCCESS; + + if (NULL == (pNvramData = malloc(sizeof(NVRAM_DATA)))) + { + fprintf(stderr, "Memory allocation failed"); + return ERROR; + } + + // Get a copy of the nvram before we do the image write operation + if (nandReadNvramData(pNvramData)) + { + unsigned int flags=0; + ret = getFlashInfo(&flags); + if (!IS_ERR(ret)) + { + if (flags & FLASH_INFO_FLAG_NAND) + { /* NAND flash */ + char *rootfs_part = "image_update"; + int rc; + + rc = bcmNandImageSet(rootfs_part, string, size, pNvramData); + if (rc != 0) + { + fprintf(stderr, "bcmNandImageSet failed, rc=%d", rc); + ret = ERROR; + } + } + else + { /* NOR flash */ + fprintf(stderr, "This function should not be called when using NOR flash, flags=0x%x", flags); + ret = ERROR; + } + } + } + else + { + ret = ERROR; + } + + free(pNvramData); + + return ret; +} +#endif /* DESKTOP_LINUX */ + + +int validateWfiTag(void *wtp, int blksize, uint32_t btrmEnabled) +{ + unsigned int chip_id = 0; + WFI_TAG *wt = (WFI_TAG*)wtp; + + chip_id = get_chip_id(); + +#if defined(CHIP_FAMILY_ID_HEX) + chip_id = CHIP_FAMILY_ID_HEX; +#endif + +#ifdef DESKTOP_LINUX + chip_id = wt->wfiChipId; +#endif + + if( (wt->wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + wt->wfiChipId != chip_id ) + { + flashutil_error("Chip Id error. Image Chip Id = %x, Board Chip Id = %x", + wt->wfiChipId, chip_id); + return -1; + } + else if( wt->wfiFlashType == WFI_NOR_FLASH ) + { + flashutil_error("Image does not support a NAND flash device."); + return -1; + } + else if( (wt->wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS && + ((wt->wfiFlashType < WFI_NANDTYPE_FLASH_MIN && wt->wfiFlashType > WFI_NANDTYPE_FLASH_MAX) || + blksize != WFI_NANDTYPE_TO_BKSIZE(wt->wfiFlashType) ) ) + { + flashutil_error("NAND flash block size %dKB does not work with an " + "image built with %dKB block size", blksize, WFI_NANDTYPE_TO_BKSIZE(wt->wfiFlashType)); + return -1; + } + else if ( (get_flash_type() != FLASH_IFC_SPINAND) && + ((( (wt->wfiFlags & WFI_FLAG_SUPPORTS_BTRM)) && (! btrmEnabled)) || + ((! (wt->wfiFlags & WFI_FLAG_SUPPORTS_BTRM)) && ( btrmEnabled))) ) + { + flashutil_error("The image type does not match the OTP configuration of the SoC. Aborting."); + return -1; + } + + return 0; +} + +int flashCferam(mtd_info_t *mtd, int mtd_fd, int rsrvd_for_cferam, unsigned char *cferam_ptr, unsigned char *cferam_ptr2) +{ + int blk_addr; + int first_done = 0; + + flashutil_debug("enter, mtd=%p, fd=%d, rsrvd_for_cferam=0x%x", + mtd, mtd_fd, rsrvd_for_cferam); + + for( blk_addr = 0; blk_addr < rsrvd_for_cferam; blk_addr += mtd->erasesize ) + { + if( nandIsBadBlk(blk_addr, mtd_fd) == 0 ) + { + /* Write CFERAM sequence number block of the image to flash. */ + if (!first_done) + { + if (nandWriteBlk(mtd, blk_addr, cferam_ptr ? mtd->erasesize : 0, cferam_ptr, mtd_fd, 1) == 0) + { // rsrvd_for_cferam number of blocks reserved for CFERAM block in order to guarantee at least one block good, CFERAM block with cferam entry written last, write only one block and leave the rest blank, cferom/filesystem must patch this back together + printf("."); + + if (!cferam_ptr2) + { + fflush(stdout); + return(0); + } + + first_done = 1; + continue; + } + } + else + { + if (nandWriteBlk(mtd, blk_addr, cferam_ptr2 ? mtd->erasesize : 0, cferam_ptr2, mtd_fd, 1) == 0) + { // write second CFERAM block if there is one + printf("."); + fflush(stdout); + + return(0); + } + } + } + } + + return(-1); +} + +/* + hunt_ptr - pointer to the buffer that holds the gen3 boot block + the boot block contains NVRAM_DATA and the CFEROM images + NVRAM_DATA images is prefixed with "nVrAmDat" signature + whereas CFEROM has its own header and signature + size_to_search - size of the boot block, typically 1MB + nvram_mirror_info - this function will populate this structure based on what is found in the input buffer +*/ +static void populate_boot_block_info_struct(char *hunt_ptr, int size_to_search, PNVRAM_DATA pnd, BOOT_BLOCK_MIRROR_INFO *nvram_mirror_info, mtd_info_t *mtd) +{ + char *saved_hunt_ptr=hunt_ptr; + int nvram_mirr_info_idx=0, rom_size=0, cferom_crc=0; + + if(hunt_ptr != NULL && nvram_mirror_info != NULL) + { + memset(nvram_mirror_info,'\0',sizeof(BOOT_BLOCK_MIRROR_INFO)); + nvram_mirror_info->active_idx=0; // always make the primary as active + nvram_mirror_info->offset[nvram_mirr_info_idx]=nvramDataOffset(mtd); + nvram_mirror_info->image_type[nvram_mirr_info_idx]=IMG_NVRAM; + nvram_mirror_info->write_fail_count[nvram_mirr_info_idx]=0; + nvram_mirror_info->cferom_crc=0; + nvram_mirr_info_idx++; + + + while(size_to_search > 2048) + { + if(is_nvram_offset((unsigned char*)hunt_ptr, 0, 1, NULL, NULL) == IMG_NVRAM) + { + nvram_mirror_info->offset[nvram_mirr_info_idx]=(hunt_ptr - saved_hunt_ptr); + nvram_mirror_info->image_type[nvram_mirr_info_idx]=IMG_NVRAM; + nvram_mirror_info->write_fail_count[nvram_mirr_info_idx]=0; + nvram_mirr_info_idx++; + memcpy(hunt_ptr+strlen(NVRAM_DATA_SIGN), (unsigned char *)pnd, sizeof(NVRAM_DATA)); + } + + else if(is_cferom_offset((unsigned char*)hunt_ptr, 0, &rom_size, &cferom_crc, NULL) == IMG_CFEROM) + { + nvram_mirror_info->offset[nvram_mirr_info_idx]=(hunt_ptr - saved_hunt_ptr); + nvram_mirror_info->image_type[nvram_mirr_info_idx]=IMG_CFEROM; + nvram_mirror_info->image_size[nvram_mirr_info_idx]=rom_size; + nvram_mirror_info->write_fail_count[nvram_mirr_info_idx]=0; + if(nvram_mirror_info->cferom_crc == 0) + nvram_mirror_info->cferom_crc=cferom_crc; + nvram_mirr_info_idx++; + } + hunt_ptr+=1024; + size_to_search-=1024; + } + } +} +/* + Write the nvram_mirror_info struture to BOOT_BLOCK_MIRROR_INFO_FILE file +*/ +static void write_boot_block_info_file(BOOT_BLOCK_MIRROR_INFO *nvram_mirror_info) +{ + int fd=0; + int status=0; + + fd=open(BOOT_BLOCK_MIRROR_INFO_FILE, O_CREAT|O_WRONLY|O_TRUNC, 0644); + + if(fd) + { + status=write(fd, nvram_mirror_info, sizeof(*nvram_mirror_info)); + if(status == -1) + printf("error writing %s file\n", BOOT_BLOCK_MIRROR_INFO_FILE); + close(fd); + sync(); + } + +} +/* + populate the nvram_mirror_info by searching through input buffer + and write the struture to BOOT_BLOCK_MIRROR_INFO_FILE file +*/ +void create_boot_block_info_file(char *ptr, int size, PNVRAM_DATA pnd, mtd_info_t *mtd ) +{ + BOOT_BLOCK_MIRROR_INFO nvram_mirror_info; + populate_boot_block_info_struct(ptr, size, pnd, &nvram_mirror_info, mtd); + write_boot_block_info_file(&nvram_mirror_info); +} + +int handleCferom(mtd_info_t *mtd, char *image_ptr,unsigned int image_size __attribute__ ((__unused__)), unsigned int wfiFlags, void *inMemNvramData) +{ + int nvramXferSize; + NVRAM_DATA *inMemNvramData_buf = (NVRAM_DATA*)inMemNvramData; + + /* Downloaded image contains CFE ROM boot loader. */ + PNVRAM_DATA pnd = (PNVRAM_DATA) (image_ptr + nvramSector(mtd) * ((unsigned int)mtd->writesize) + nvramDataOffset(mtd)); + + flashutil_debug("enter, mtd=%p, image=%p, wfiFlags=%d, nvram=%p", + mtd, image_ptr, wfiFlags, inMemNvramData_buf); + + if( verifyImageDDRType(wfiFlags, inMemNvramData_buf) != 0 ) + return -1; + +#if defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148) || defined(CONFIG_BCM96858) || defined(CONFIG_BCM94908) +#if defined(CONFIG_BCM94908) + if(get_flash_type() == FLASH_IFC_NAND ) { + if(nand_image_type((unsigned char*)image_ptr) == 0) + { + int remain = IMAGE_OFFSET%mtd->erasesize; + memset(image_ptr, '\0', remain); + } + } + else if(get_flash_type() != FLASH_IFC_SPINAND) { +#endif + /* check if it is zero padded for backward compatiblity */ + if( (wfiFlags&WFI_FLAG_HAS_PMC) == 0 ) + { + unsigned int *pImg = (unsigned int*)image_ptr; + unsigned char * pBuf = (unsigned char*)image_ptr; + int block_start, block_end, remain, block; + mtd_info_t *mtd1; + int mtd1_fd; + + if( *pImg == 0 && *(pImg+1) == 0 && *(pImg+2) == 0 && *(pImg+3) == 0 ) + { + /* the first 64KB are for PMC in 631x8, need to preserve that for cfe/linux image update if it is not for PMC image update. */ + block_start = 0; + block_end = IMAGE_OFFSET/mtd->erasesize; + remain = IMAGE_OFFSET%mtd->erasesize; + + mtd1 = get_mtd_device_handle("nvram", &mtd1_fd, 0); + if( !IS_ERR_OR_NULL(mtd1) ) + { + for( block = block_start; block < block_end; block++ ) + { + nandReadBlk(mtd1, block*mtd1->erasesize, mtd1->erasesize, pBuf, mtd1_fd); + pBuf += mtd1->erasesize; + } + + if( remain ) + { + block = block_end; + nandReadBlk(mtd1, block*mtd1->erasesize, remain, pBuf, mtd1_fd); + } + + put_mtd_device(mtd1, mtd1_fd, -1); + } + else + { + fprintf(stderr, "Failed to get nvram mtd device\n"); + return -1; + } + } + else + { + fprintf(stderr, "Invalid NAND image.No PMC image or padding\n"); + return -1; + } + } +#if defined(CONFIG_BCM94908) + } +#endif +#else + flashutil_print("wfiFlags=%d", wfiFlags); +#endif + + nvramXferSize = sizeof(NVRAM_DATA); + + /* Copy NVRAM data to block to be flashed so it is preserved. */ + memcpy((unsigned char *) pnd, inMemNvramData_buf, nvramXferSize); + + /* Recalculate the nvramData CRC. */ + pnd->ulCheckSum = 0; + pnd->ulCheckSum = genUtl_getCrc32((unsigned char *)pnd, sizeof(NVRAM_DATA), CRC32_INIT_VALUE); + + unlink(BOOT_BLOCK_MIRROR_INFO_FILE); + + return 0; +} + + +int flashCferom(unsigned char *image_ptr, unsigned int size) +{ + /* Prepare to flash the CFE ROM boot loader. */ + int mtd_fd; + mtd_info_t *mtd = get_mtd_device_handle("nvram", &mtd_fd, 0); + int address = 0; + int status = 0; + BOOT_BLOCK_MIRROR_INFO nvram_mirror_info; + + /* Downloaded image contains CFE ROM boot loader. */ + PNVRAM_DATA pnd = (PNVRAM_DATA) (image_ptr + nvramSector(mtd) * ((unsigned int)mtd->writesize) + nvramDataOffset(mtd)); + + printf("\n+\n"); + + populate_boot_block_info_struct((char*)image_ptr, size, pnd, &nvram_mirror_info, mtd); //skip first page as 4908 has precferom + + flashutil_debug("enter, image=%p, size=%d", + image_ptr, size); + + if( !IS_ERR_OR_NULL(mtd) ) + { + while(size) + { + int iterations = 3; + + while(iterations--) + { + if (nandEraseBlk(mtd, address, mtd_fd) == 0) + { + if (nandWriteBlk(mtd, address, mtd->erasesize, image_ptr, mtd_fd, 1) != 0) + { + printf("ERROR WRITING CFE ROM BLOCK AT ADDRESS 0x%x!!!\n", address); + if (iterations == 1) + status = -1; + } + else + break; + } + else + { + printf("ERROR ERASING CFEROM BLOCK AT ADDRESS 0x%x!!!\n", address); + if (iterations == 1) + status = -1; + } + } + + image_ptr += mtd->erasesize; + address += mtd->erasesize; + size -= mtd->erasesize; + } + + put_mtd_device(mtd, mtd_fd, -1); + } + else + { + flashutil_error("Failed to get nvram mtd device!!!"); + return -1; + } + printf("\n+\n"); + if(get_flash_type() == FLASH_IFC_NAND || get_flash_type() == FLASH_IFC_SPINAND ) { + write_boot_block_info_file(&nvram_mirror_info); + printf("\n+\n"); + } + + return(status); +} + +int nandFlashLoader(unsigned char *file_name, uint64_t file_size) +{ + /* Prepare to flash the uboot boot loader. */ + int mtd_fd; + mtd_info_t *mtd = get_mtd_device_handle("loader", &mtd_fd, 0); + int address = 0; + int status; + FILE* file_ptr; + unsigned char * image_ptr = NULL; + int bytes_read = 0; + int part_size; + + flashutil_debug("enter, image=%p, size=%d", + image_ptr, file_size); + + if( !IS_ERR_OR_NULL(mtd) ) + { + image_ptr = malloc(mtd->erasesize); + if( !image_ptr ) + { + printf("%s: Error, cannot allocate memory for writing\n", __FUNCTION__); + put_mtd_device(mtd, mtd_fd, -1); + return -1; + } + + file_ptr = fopen((char*)file_name, "r"); + if( !file_ptr ) + { + printf("%s: Error, cannot open %s\n", __FUNCTION__, file_name); + free( image_ptr ); + put_mtd_device(mtd, mtd_fd, -1); + return -1; + } + + part_size = mtd->size; + status = 0; + + flashutil_debug(">>>>>>>> partition size 0x%x, file size 0x%llx <<<<<<<<\n", part_size, file_size); + + while((file_size > 0) && (part_size > 0)) + { + if (!status) + bytes_read = fread(image_ptr, mtd->erasesize, 1, file_ptr); + + status = -1; + if( bytes_read ) + { + if( nandIsBadBlk(address, mtd_fd) == 0 ) + { + int iterations = 3; + while(iterations--) + { + if (nandEraseBlk(mtd, address, mtd_fd) == 0) + { + if (nandWriteBlk(mtd, address, mtd->erasesize, image_ptr, mtd_fd, 0) != 0) + { + printf("ERROR WRITING LOADER AT ADDRESS 0x%x!!!\n", address); + } + else + { + status = 0; + break; + } + } + else + { + printf("ERROR ERASING LOADER BLOCK AT ADDRESS 0x%x!!!\n", address); + } + } + } + + if (status) + printf("Skipping bad block at 0x%x\n", address); + + } + + flashutil_debug(">>>>>>>> %s file offset 0x%x to partition offset 0x%x <<<<<<<<\n", status ? "did not write" : "wrote", mtd->size - (int)file_size, address); + + address += mtd->erasesize; + part_size -= mtd->erasesize; + + if (!status) + file_size -= mtd->erasesize; + } + + fclose(file_ptr); + free(image_ptr); + put_mtd_device(mtd, mtd_fd, -1); + + } + else + { + flashutil_error("Failed to get loader mtd device!!!"); + return -1; + } + + printf("Flashing loader finished\n"); + + return(0); +} + +int nandGetImageVersion(uint8_t *imagePtr, int imageSize, char *image_name, int image_name_len) +{ + mtd_info_t *mtd; + int mtd_fd; + int ret = -1; + + mtd = get_mtd_device_handle("image", &mtd_fd, 0); + if (!IS_ERR_OR_NULL(mtd)) + { + ret = get_image_version(imagePtr, imageSize, mtd->erasesize, image_name, image_name_len); + put_mtd_device(mtd, mtd_fd, -1); + } + return ret; +} + +uint64_t nandGetAvailImgSpace( int update_img_idx ) +{ + char sysfs_path[128]; + uint64_t erase_blk_size = 0; + uint64_t avail_erase_blks = 0; + uint64_t avail_size = 0; + + sprintf(sysfs_path,"/sys/class/ubi/ubi0/eraseblock_size"); + erase_blk_size = getSysfsBytes(sysfs_path); + sprintf(sysfs_path,"/sys/class/ubi/ubi0/avail_eraseblocks"); + avail_erase_blks = getSysfsBytes(sysfs_path); + avail_size = erase_blk_size * avail_erase_blks; + + /* Bootfs size */ + sprintf(sysfs_path,"/sys/class/ubi/ubi0_%d/reserved_ebs",(update_img_idx==1?3:5)); + avail_erase_blks = getSysfsBytes(sysfs_path); + avail_size += erase_blk_size * avail_erase_blks; + + /* Rootfs size */ + sprintf(sysfs_path,"/sys/class/ubi/ubi0_%d/reserved_ebs",(update_img_idx==1?4:6)); + avail_erase_blks = getSysfsBytes(sysfs_path); + avail_size += erase_blk_size * avail_erase_blks; + + return avail_size; +} + +uint64_t nandGetAvailLoaderSpace(void) +{ + uint64_t loader_size; + char sysfs_path[] = "/sys/class/mtd/mtd1/size"; + loader_size = getSysfsBytes(sysfs_path); + return loader_size; +} + +int get_mtd_master_size(unsigned int *psize __attribute__((unused))) +{ +#ifndef DESKTOP_LINUX + uint64_t size = 0; + char sysfs_path[] = "/sys/class/mtd/mtd0/size"; + + size = getSysfsBytes(sysfs_path); + *psize = (unsigned int)(size/1024); +#endif + + return(0); +} + +/* mdev can take upto 2 seconds to create dev_nodes */ +#define DEV_NODE_CREATE_TIMEOUT_USEC 3000000 +#define DEV_NODE_CREATE_CHK_INTRVL_USEC 500000 +int nandUbiVolDevNodeExists( char * dev_path ) +{ + int dev_node_create_wait_cnt=DEV_NODE_CREATE_TIMEOUT_USEC; + + /* If we have just created a ubi volume mdev might take upto 2 seconds + * to create the associated dev_nodes, so we wait and check every .5s + */ + while( dev_node_create_wait_cnt > 0 ) + { + /* If node doesnt exist we sleep and check again */ + if( access( dev_path, F_OK ) ) + { + usleep(DEV_NODE_CREATE_CHK_INTRVL_USEC); + dev_node_create_wait_cnt -= DEV_NODE_CREATE_CHK_INTRVL_USEC; + } + else + break; + } + + return (dev_node_create_wait_cnt>0); +} + +int getNandMetadata( char * data, int size , int mdata_idx) +{ + char mdata_fname[128]; + FILE * mdata_fh; + int num_bytes = 0; + sprintf(mdata_fname, "/dev/ubi0_%d", mdata_idx); + mdata_fh = fopen(mdata_fname, "r"); + + if( mdata_fh ) + { + num_bytes = fread(data, 1, size, mdata_fh); + + if( ferror(mdata_fh) ) + { + printf("%s: Error fread metadata%d!\n", __FUNCTION__, mdata_idx); + num_bytes = 0; + } + + fclose(mdata_fh); + } + else + { + printf("%s: Error fopen metadata%d!\n", __FUNCTION__, mdata_idx); + } + + return num_bytes; +} + +int setNandMetadata( char * data, int size, int mdata_idx ) +{ + FILE * mdata_fh = fopen("/var/mdata.tmp", "w"); + char cmd[128]; + int rc = 0; + if( mdata_fh ) + { + fwrite(data, 1, size, mdata_fh); + fclose(mdata_fh); + } + else + { + printf("%s: Error writing metadata!\n", __FUNCTION__); + return -1; + } + + /* Create Metadata device if it doesnt exist */ + sprintf(cmd, "/dev/ubi0_%d", mdata_idx) ; + if( access( cmd, F_OK ) ) + { + sprintf(cmd, "ubimkvol /dev/ubi0 -s %d -n %d -N metadata%d --type=static", size, mdata_idx, mdata_idx); + flashutil_debug("=> %s\n", cmd); + rc = system(cmd); + if( rc ) + goto err_exit; + } + + /* Update volume with metadata */ + sprintf(cmd, "/dev/ubi0_%d", mdata_idx); + if( nandUbiVolDevNodeExists(cmd) ) + { + sprintf(cmd, "ubiupdatevol /dev/ubi0_%d /var/mdata.tmp", mdata_idx); + flashutil_debug("=> %s\n", cmd); + rc = system(cmd); + rc |= system("rm -rf /var/mdata.tmp"); + if (rc < 0) + { + fprintf(stderr, "ERROR!!! ubi command failed!\n"); + } + } + else + { + fprintf(stderr, "ERROR!!! %s doesnt exist!\n", cmd); + rc = -1; + } + +err_exit: + return rc; +} + + +/*********************************************************************** + * Function Name: nandCommit + * Description : Gets/sets the commit flag of a pureUBI image. + * Returns : 0 - success, -1 - failure + ***********************************************************************/ +int nandCommit( int partition, char *commit_flag ) +{ + int ret = -1; + int mtd_fd, mtdblock_fd; + mtd_info_t * mtd; + int i; + unsigned char * buf = NULL; + unsigned int len; + int write = (*commit_flag != 0); + + if( nandIsLegacyFlashLayout()) + { + if (partition == nandGetBootPartition()) + { // use UBI interface + if (!exist_mtd_dev_nm("METADATA") && !exist_mtd_dev_nm("METADATACOPY")) + return(ret); + + for (i = 0; i < 2; i++) + { + mtd = get_mtd_device_handle(i ? "METADATACOPY" : "METADATA", &mtd_fd, &mtdblock_fd); + + if ( IS_ERR_OR_NULL(mtd) ) + { + fprintf(stderr, "ERROR!!! unable to open mtd partition %s\n", i ? "METADATACOPY" : "METADATA"); + continue; + } + + len = mtd->erasesize; + + if ( !buf && ((buf = malloc(len)) == 0) ) + { + fprintf(stderr, "ERROR!!! cannot allocate block memory for buffer\n"); + put_mtd_device(mtd, mtd_fd, mtdblock_fd); + continue; + } + + if (parse_ubi(0, buf, 0, mtd->size / len, len, -1, "committed", commit_flag, 0, 0, read_block, write ? write_block : 0, /* write ? erase_block :*/ 0, mtd, mtdblock_fd) == 1) + { + ret = 0; // if either copy of metadata is committed then we are committed + if (!write) + { + put_mtd_device(mtd, mtd_fd, mtdblock_fd); + break; + } + } + else + printf("ERROR!!! Could not find %s partition image metadata volume %d\n", (partition == 1) ? "first" : "second", i); + + put_mtd_device(mtd, mtd_fd, mtdblock_fd); + } + + if (buf) + free(buf); + } + else + { // use mtd interface + if (scan_partition("image_update") != UBI_IMAGE) + return(ret); + + mtd = get_mtd_device_handle("image_update", &mtd_fd, 0); + + if ( IS_ERR_OR_NULL(mtd) ) + { + fprintf(stderr, "ERROR!!! unable to open mtd partition image_update\n"); + return(ret); + } + + len = mtd->erasesize; + + if ((buf = malloc(len)) == 0) + { + fprintf(stderr, "ERROR!!! cannot allocate block memory for buffer\n"); + put_mtd_device(mtd, mtd_fd, -1); + return(ret); + } + + for (i = 0; i < 2; i++) + { + if (parse_ubi(0, buf, 0, mtd->size / len, len, i ? VOLID_METADATA_COPY : VOLID_METADATA, "committed", commit_flag, 0, 0, read_blk, write ? write_blk : 0, write ? erase_blk : 0, mtd, mtd_fd) == 1) + { + ret = 0; // if either copy of metadata is committed then we are committed + if (!write) + break; + } + else + printf("ERROR!!! Could not find image_update metadata volume %d\n", i); + } + + put_mtd_device(mtd, mtd_fd, -1); + free(buf); + } + } + else + { + printf("ERROR!!! This function should not be called for NEW flash layout\n"); + } + + return( ret ); +} + + +/*********************************************************************** + * Function Name: nandIsBootDevice + * Description : Determines whether boot device is nand + * Returns : 0 - bootdevice is not nand, 1 - bootdevice IS nand + ***********************************************************************/ +int nandIsBootDevice(void) +{ + int found = 0; +#ifndef DESKTOP_LINUX + FILE *fp; + char line[COMMAND_LINE_SIZE]={0}; +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + fp = popen("/etc/get_rootfs_dev.sh", "r"); +#else + fp = popen("/rom/etc/get_rootfs_dev.sh", "r"); +#endif + if (fp == NULL) { +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + printf("Failed to run /etc/get_rootfs_dev.sh command\n" ); +#else + printf("Failed to run /rom/etc/get_rootfs_dev.sh command\n" ); +#endif + return 0; + } + + if(fgets(line, sizeof(line), fp)) + { + if ( strstr(line, "ubiblock") || strstr(line, "ubi:rootfs") ) + found = 1; + } + pclose(fp); +#endif + return found; +} + + +/*********************************************************************** + * Function Name: nandIsLegacyFlashLayout + * Description : Determines whether boot device is using legacy flash layout + * Returns : 1 - flashlayout is legacy + ***********************************************************************/ +int nandIsLegacyFlashLayout(void) +{ + FILE *fp; + char line[256]={0}; + char *mtd_name = "\"loader\""; + char name[MAX_MTD_NAME_SIZE]={0}; + int legacy_layout = 1; + + fp = fopen("/proc/mtd","r"); + if (fp == NULL) + { + fprintf(stderr, "Could not open /proc/mtd"); + return ERROR; + } + + /* Search for 'loader' partition from new flash layout */ + while(fgets(line, sizeof(line), fp)) + { + sscanf(line, "%*s %*s %*s %s", name); + + if(strcmp(mtd_name, name) == 0) + { + legacy_layout = 0; + break; + } + } + fclose(fp); + return legacy_layout; +} + +/*********************************************************************** + * Function Name: getBootedValue (devCtl_getBootedImagePartition) + * Description : Gets the state of an image update from flash. + * Returns : state constant or -1 for failure + ***********************************************************************/ +extern int devCtl_getBootedImageId(void); + +int nandGetBootedValue(void) +{ + if (nandGetBootPartition() == 1) + return(BOOTED_PART1_IMAGE); + else + return(BOOTED_PART2_IMAGE); +} + +/* + calculates and compare checksum for CFEROM binary +*/ +static int chksum_sbi(unsigned char *pSbi, int *cferom_crc) +{ + // sbiLen is the length of the entire UBI image including the 4 byte CRC + SbiUnauthHdrBeginning *pUHdr = (SbiUnauthHdrBeginning *)pSbi; + uint32_t sbiLen = pUHdr->sbiSize; + uint32_t unauthHdrSize = pUHdr->hdrLen; + unsigned char *pCrcStart = pSbi + unauthHdrSize; + uint32_t crcLen = sbiLen - (RSA_S_MODULUS8 * 2) - unauthHdrSize - CRC_LEN; + uint32_t crc = CRC_INITIAL_VALUE; + + + // We are about to authenticate the UBI itself, print out "UBI?" + // Perform the CRC calc + // crc is only across the same data that the signature is across + // therefore exclude the unauthenticated header, and the trailer + crc = genUtl_getCrc32(pCrcStart, crcLen, crc); + + if (memcmp(&crc, pSbi + sbiLen - CRC_LEN, CRC_LEN) != 0) + { + // we have failed the UBI image crc, print out "UBIF" + return -1; + } + + if(cferom_crc != NULL) + *cferom_crc=crc; + + // we have passed the UBI image crc, print out "UBIP" + return 0; +} + +/* + This function will check if thre is a valid CFEROM binary at the start of the buffer + if save_cferom is not NULL, it will allocate required amount of memory and copy the cferom + into that buffer +*/ +int is_cferom_offset(unsigned char *buffer, int offset, int *rom_size, int *cferom_crc, unsigned char **save_cferom) +{ + struct hdr_chksum { + SbiUnauthHdrBeginning unauthHdr; + uint32_t chksum; + }__attribute__((__packed__)) *hdchk; + SbiUnauthHdrBeginning *pHdr; + SbiAuthHdrBeginning *authHdrBgn; + int auth_hdr_offset=0; + uint32_t crc = CRC32_INIT_VALUE; + int rc=0; + + hdchk=( struct hdr_chksum *)(buffer+offset); + if (hdchk->unauthHdr.magic_1 == BTRM_SBI_UNAUTH_MGC_NUM_1) + { + if (hdchk->unauthHdr.magic_2 == BTRM_SBI_UNAUTH_MGC_NUM_2) + { + //verify image + // Do a preliminary upper / lower boundary check of the size of the unauthenticated header + if ((hdchk->unauthHdr.hdrLen >= sizeof(SbiUnauthHdrBeginning)) && (hdchk->unauthHdr.hdrLen < BTRM_SBI_UNAUTH_HDR_MAX_SIZE)) + { + // Perform a CRC calc on the header + pHdr=&hdchk->unauthHdr; + crc = CRC32_INIT_VALUE; + crc = genUtl_getCrc32((uint8_t*)pHdr, hdchk->unauthHdr.hdrLen-sizeof(uint32_t), crc); + if (memcmp(&crc, ((uint8_t*)pHdr) + (hdchk->unauthHdr.hdrLen-sizeof(uint32_t)), CRC_LEN) == 0) + { + // + if (hdchk->unauthHdr.sbiSize < BTRM_SBI_IMAGE_MAX_ALLOWED_SIZE) + { + // Check that the sbi size value is at least big enough integer to cover the + // unauthenticated header and trailer. + if (hdchk->unauthHdr.sbiSize <= ((RSA_S_MODULUS8 * 2) + hdchk->unauthHdr.hdrLen + CRC_LEN)) + { + // Print out "UHDF" which stands for "Unath HeaDer Failed" + } + else + { + //get the image + auth_hdr_offset=offset+hdchk->unauthHdr.hdrLen; + authHdrBgn = (SbiAuthHdrBeginning *)(buffer+auth_hdr_offset); + //ppCopyFunc(auth_hdr_offset, (unsigned char *)&authHdrBgn, sizeof(SbiAuthHdrBeginning)); + // Retrieve the (untrusted) authHdrSize from the header itself + // Do a preliminary upper / lower boundary check of the authenticated header size + if ((authHdrBgn->hdrLen < sizeof(SbiAuthHdrBeginning)) || (authHdrBgn->hdrLen > BTRM_SBI_AUTH_HDR_MAX_SIZE)) + { + } + else + { + // Make sure that the COTs within the authenticated header are such that everything in + // this header is word aligned. For example, mfg ROE COT version 2 should have 2 bytes of padding + if (authHdrBgn->hdrLen % sizeof(uint32_t) != 0) + { + } + else + { + //checksum sbi + rc=chksum_sbi((unsigned char*)(buffer+offset), cferom_crc); + if(rc == 0) + { + if(save_cferom != NULL ) + { + if(save_cferom[0] == NULL) + save_cferom[0]=malloc(hdchk->unauthHdr.sbiSize); + if(save_cferom[0] != NULL) + { + memcpy(save_cferom[0], buffer+offset, hdchk->unauthHdr.sbiSize); + *rom_size=hdchk->unauthHdr.sbiSize; + } + } + + rc=IMG_CFEROM; + } + //prev_offset=offset; + //break; + } + } + } + + } + } + + } + } + } + return rc; +} +/* + function checks for the NVRAM_DATA_SIGN at the beginning of the buffer + if found it will perform the checksum check on the data that follows the signature + if check_nvram_data_sign is 0, the NVRAM_DATA_SIGN will not be checked +*/ +int is_nvram_offset(unsigned char *buffer, int offset, int check_nvram_data_sign, int *image_size, PNVRAM_DATA current_nvram) +{ + char *sign=NVRAM_DATA_SIGN; + unsigned int crc, temp_crc; + int rc=IMG_MISSING; + + if(!check_nvram_data_sign) + { + sign="\0"; + } + if(strncmp((char*)buffer+offset, sign, strlen(sign)) == 0) + { + crc=((PNVRAM_DATA)(buffer+offset+strlen(sign)))->ulCheckSum; + ((PNVRAM_DATA)(buffer+offset+strlen(sign)))->ulCheckSum=0; + if(crc == (temp_crc=genUtl_getCrc32((unsigned char *) (buffer+offset+strlen(sign)), sizeof(NVRAM_DATA), CRC_INITIAL_VALUE))) + { + rc=IMG_NVRAM; + if(current_nvram != NULL) + if(crc != current_nvram->ulCheckSum) + rc=CRC_MISMATCH; + if(image_size != NULL) + *image_size=sizeof(NVRAM_DATA)+strlen(sign); + } + else + { + rc=CRC_MISMATCH; + } + //restore the crc + ((PNVRAM_DATA)(buffer+offset+strlen(sign)))->ulCheckSum=crc; + } + return rc; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nand.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nand.h new file mode 100755 index 00000000000..6a5df3d7407 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nand.h @@ -0,0 +1,90 @@ +/*********************************************************************** + * + * Copyright (c) 2011 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2011:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + + +#ifndef _BCM_FLASHUTIL_NAND_H__ +#define _BCM_FLASHUTIL_NAND_H_ + +#include +#include + +#include "bcm_hwdefs.h" + + +/* Used by bcm_imgif, bcm_imgutil, image.c*/ +unsigned char *nandUpdateSeqNum(unsigned char *imagePtr, int imageSize, int blkLen, int seq, int *found); +int nand_image_type(unsigned char * buf); +mtd_info_t *get_mtd_device_handle(const char *check, int *mtd_fd, int *mtdblock_fd); +void put_mtd_device(mtd_info_t *mtd, int mtd_fd, int mtdblock_fd); +int get_mtd_device_name(const char * check __attribute__((unused)), char * device __attribute__((unused))); +int get_mtd_master_size(unsigned int *psize); +int nandEraseBlk(mtd_info_t *mtd, int blk_addr, int mtd_fd); +int nandWriteBlk(mtd_info_t *mtd, int blk_addr, int data_len, unsigned char *data_ptr, + int mtd_fd, int write_JFFS2_clean_marker); +int flashCferam(mtd_info_t *mtd, int mtd_fd, int rsrvd_for_cferam, + unsigned char *cferam_ptr, unsigned char *cferam_ptr2); +int handleCferom(mtd_info_t *mtd0, char *image_ptr, unsigned int image_size, unsigned int wfiFlags, + void *inMemNvramData_buf); +int flashCferom(unsigned char *image_ptr, unsigned int size); +int validateWfiTag(void *wt, int blksize, uint32_t btrmEnabled); + +unsigned int nvramDataOffset(const mtd_info_t * mtd __attribute__((unused))); + +/* Used by bcm_flashutil.c */ +int nandReadNvramData(void *nvramData); +int nandGetSequenceNumber(int imageNumber); +int nandGetImageVersion(uint8_t *imagePtr, int imageSize, char *image_name, int image_name_len); +int nandWriteBootImageState( int newState ); +int nandReadBootImageState( void ); +int nandUpdateSequenceNumber(int incSeqNumPart, int seqPart1, int seqPart2); +int nandIsBootDevice(void); +int nandGetBootedValue(void); +int nandGetBootPartition(void); +int nandCommit( int partition, char *commit_flag ); +int nandSetImgValidStatus( int img_idx, int valid); +int nandIsLegacyFlashLayout(void); +int nandUbiVolDevNodeExists( char * dev_path ); +uint64_t nandGetAvailImgSpace( int update_img_idx ); +uint64_t nandGetAvailLoaderSpace(void); +int getNandMetadata( char * data, int size , int mdata_idx); +int setNandMetadata( char * data, int size, int mdata_idx ); +int nandFlashLoader(unsigned char *file_name, uint64_t file_size); + +/* used by housekeeping task that keeps nvram mirror and cferom integrity */ +int is_cferom_offset(unsigned char *buffer, int offset, int *img_size, int *cferom_crc, unsigned char **); +int is_nvram_offset(unsigned char *buffer, int offset, int nvram_sign_check, int *img_size, PNVRAM_DATA); +void create_boot_block_info_file(char *hunt_ptr, int size_to_search, PNVRAM_DATA pnd, mtd_info_t *mtd); +#define RSA_S_MODULUS 2048 /* Bits in a key modulus */ +#define RSA_S_MODULUS8 (RSA_S_MODULUS/8) /* Bytes in a key modulus */ +#define BTRM_SBI_UNAUTH_MGC_NUM_1 183954 +#define BTRM_SBI_UNAUTH_MGC_NUM_2 145257 + + +#endif /* _BCM_FLASHUTIL_NAND_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nor.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nor.c new file mode 100644 index 00000000000..7228cac343a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nor.c @@ -0,0 +1,145 @@ +/*********************************************************************** + * <:copyright-BRCM:2007:DUAL/GPL:standard + * + * Copyright (c) 2007 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +#include +#include +#include // types +#include +#include +#include +#include +#include + +#include "bcm_flashutil.h" +#include "bcm_flashutil_nor.h" + + +int norIsNewFlashLayout(void) +{ + FILE *fp; + char line[256]={0}; + char *spinorflash = SPI_NOR_FLASH_NAME; + int new_layout = 0; + + fp = fopen("/proc/cmdline","r"); + if (fp == NULL) + { + fprintf(stderr, "Could not open /proc/cmdline"); + return 0; + } + + /* Search for 'spinorflash0' from cmdline*/ + while(fgets(line, sizeof(line), fp)) + { + if(strstr(line, spinorflash)) + { + new_layout = 1; + break; + } + } + fclose(fp); + return new_layout; +} + +uint64_t spinorGetAvailSpace(const char* mtdpart) +{ + uint64_t loader_size; + char sysfs_path[128]; + sprintf(sysfs_path, "/sys/class/mtd/%s/size",mtdpart); + loader_size = getSysfsBytes(sysfs_path); + return loader_size; +} + +static void print_imgupdate_progress() +{ + fprintf(stderr, "."); +} + +int norWriteFileToMtdPar(const char* filename,const char* mtdpart) +{ + mtd_info_t mtd_info; + int mtd_fd; + erase_info_t ei; + char* buff; + int file_fd; + int more =1; + int read_couter=0; + int ret = 0; + + if ((mtd_fd = open(mtdpart, O_SYNC|O_RDWR)) < 0) + { + fprintf(stderr, "ERROR!!! Could not open %s\n", mtdpart); + return (-1); + } + ioctl(mtd_fd, MEMGETINFO, &mtd_info); + ei.length = mtd_info.erasesize; + if ( (buff = malloc(mtd_info.erasesize)) == 0) + { + fprintf(stderr, "ERROR!!! Could not allocate buffer!\n"); + close(mtd_fd); + return (-1); + } + if ((file_fd = open(filename, O_RDONLY)) < 0) + { + fprintf(stderr, "ERROR!!! Could not open %s\n", filename); + close(mtd_fd); + free(buff); + return (-1); + } + for(ei.start = 0; ei.start < mtd_info.size; ei.start += mtd_info.erasesize) + { + ioctl(mtd_fd, MEMUNLOCK, &ei); + if( ioctl(mtd_fd, MEMERASE, &ei) < 0) + { + fprintf(stderr, "ERROR!!! Fail to erase partition %s\n",mtdpart); + ret = -1; + break; + } + if(more) + { + read_couter = read(file_fd, buff, mtd_info.erasesize); + if( read_couter > 0) + { + if( write(mtd_fd,buff,read_couter) != read_couter) + { + fprintf(stderr,"ERROR!!! Fail to flash into partition %s\n",mtdpart); + ret = -1; + break; + } + } + if((read_couter == 0) || (read_couter < mtd_info.erasesize)) + more = 0; + } + print_imgupdate_progress(); + } + close(mtd_fd); + close(file_fd); + free(buff); + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nor.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nor.h new file mode 100644 index 00000000000..88c4a6302f8 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_nor.h @@ -0,0 +1,48 @@ +/*********************************************************************** + * + * Copyright (c) 2011 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2011:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + + +#ifndef _BCM_FLASHUTIL_NOR_H__ +#define _BCM_FLASHUTIL_NOR_H_ + +#define SPI_NOR_FLASH_NAME "spi-nor.0" +#define SPI_NOR_ROOTFS_MTD_NAME "rootfs" +#define SPI_NOR_BOOTFS_MTD_NAME "bootfs" +//define spinor uboot mtd partition table +#define SPI_NOR_MTD "mtd0" +#define SPI_NOR_LOADER_MTD "mtd1" +#define SPI_NOR_BOOTFS_MTD "mtd2" +#define SPI_NOR_ROOTFS_MTD "mtd3" +#define SPI_NOR_DATAMTD "mtd4" + +int norIsNewFlashLayout(void); +uint64_t spinorGetAvailSpace(const char* mtdpart); +int norWriteFileToMtdPar(const char* filename,const char* mtdpart); +#endif /* _BCM_FLASHUTIL_NAND_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_private.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_private.h new file mode 100755 index 00000000000..e0d68a22b57 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_flashutil_private.h @@ -0,0 +1,53 @@ +/*********************************************************************** + * + * Copyright (c) 2019 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2019:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + + +#ifndef _BCM_FLASHUTIL_PRIVATE_H__ +#define _BCM_FLASHUTIL_PRIVATE_H_ + +/*!\file bcm_flashutil_private.h + * \brief Internal header file for the bcm_flashutil library. This header + * is not exposed to external callers. + */ + +#include "board.h" +#include "bcm_hwdefs.h" +#include "bcm_retcodes.h" +#include "number_defs.h" + +#define IDENT_TAG "@(#) $imageversion: " + + +int verifyImageDDRType(uint32_t wfiFlags, PNVRAM_DATA pNVRAM); +BcmRet devCtl_flashConfigAccess(UINT32 boardIoctl, BOARD_IOCTL_ACTION action, + char *string, SINT32 strLen, SINT32 offset, void *data); + + +#endif /* _BCM_FLASHUTIL_PRIVATE_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgcombo.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgcombo.c new file mode 100755 index 00000000000..bfd29b07ead --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgcombo.c @@ -0,0 +1,426 @@ +/*********************************************************************** + * <:copyright-BRCM:2016:DUAL/GPL:standard + * + * Copyright (c) 2016 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +#include +#include +#include +#include + +#include "bcmTag.h" +#include "genutil_crc.h" +#include "bcm_imgutil.h" +#include "boardparms.h" +#ifdef COMBOIMG_DUMPHEX +#define DUMP_HEX(b, l) dump_hex(b, l) +#else +#define DUMP_HEX(b, l) +#endif + +#define COMBOIMG_DEBUG 0 +#define comboimg_debug(fmt, ...) \ + do { if (COMBOIMG_DEBUG) fprintf(stderr, "%s:%d(): " fmt, \ + __func__, __LINE__, ##__VA_ARGS__); } while (0) + +#define comboimg_info(fmt, ...) \ + do { fprintf(stderr, "%s:%d(): " fmt, \ + __func__, __LINE__, ##__VA_ARGS__); } while (0) + +void dump_combo_header_tag(Comboimg_header_tag *header_tag) +{ + if (!header_tag) + return; + + comboimg_info("--------------------------------------------------------------\n"); + comboimg_info("Combo image header tag:\n"); + comboimg_info("image count %u\n",header_tag->image_count); + comboimg_info("--------------------------------------------------------------\n"); +} + +void dump_individual_image_tag(Comboimg_individual_img_tag *image_tag_ptr) +{ + if (!image_tag_ptr) + return; + + comboimg_info("--------------------------------------------------------------\n"); + comboimg_info("Combo header, individual image tag:\n"); + comboimg_info("\tchip_id 0x%08x\n",image_tag_ptr->chip_id); + image_tag_ptr->board_id[BOARD_ID_LEN-1]='\0'; + comboimg_info("\tboard_id %s\n",image_tag_ptr->board_id); + comboimg_info("\timage_len %u\n",image_tag_ptr->image_len); + comboimg_info("\timage_offset %u\n",image_tag_ptr->image_offset); + comboimg_info("\timage_flags %u\n",image_tag_ptr->image_flags); + comboimg_info("\tnext_tag_offset %u\n",image_tag_ptr->next_tag_offset); + comboimg_info("\textended_image_header %u\n",image_tag_ptr->extended_image_header); + comboimg_info("--------------------------------------------------------------\n"); +} + +void dump_hex(const char *buf, UINT32 len) +{ + UINT32 i; + + for (i = 0; i < len; i++) + printf("%02X ", (unsigned char)buf[i]); + + printf("\n"); +} + +UINT32 bcmImg_rollToImage(const char *imageBuf __attribute__((unused)), + UINT32 imageLen __attribute__((unused))) +{ + return 0; +} + +static int combo_parsing_state = 0; + +UBOOL8 bcmImg_IsValidCombo(void) +{ + return (combo_parsing_state == combo_done); +} + +static char board_id[BP_BOARD_ID_LEN+5]; +imgutil_ret_e bcmImg_GetBoardId(){ +#ifndef DESKTOP_LINUX + FILE * fp = NULL; + fp = fopen("/proc/nvram/boardid","r"); + if(fp) + { + imgutil_ret_e ret = IMGUTIL_PROC_OK; + int count; + count = fscanf(fp,"%s",board_id); + if (count <= 0) + { + comboimg_info("could not fscanf board_id\n"); + ret = IMGUTIL_PROC_ERR; + } + else + comboimg_debug("boardid is %s\n",board_id); + fclose(fp); + return ret; + } + else + { + comboimg_info("unable to read boardid from procfs %s\n",board_id); + return IMGUTIL_PROC_ERR; + } +#else + return IMGUTIL_PROC_OK; +#endif +} + +imgutil_ret_e bcmImg_ComboImageInit(void) +{ + combo_parsing_state = combo_init; + return bcmImg_GetBoardId(); +} + +UBOOL8 bcmImg_ComboImageParsingDone(void) +{ + if (combo_parsing_state == combo_done || combo_parsing_state == fail + || combo_parsing_state == not_combo) + return TRUE; + else + return FALSE; +} + +imgutil_ret_e bcmImg_ComboImageIdentify(const char *imageBuf, UINT32 imageLen) +{ + const char magicnum[] = COMBOIMG_MAGIC_NUM; + DUMP_HEX(magicnum, COMBOIMG_MAGIC_NUM_LEN); + DUMP_HEX(imageBuf, imageLen); + + if (imageLen < COMBOIMG_MAGIC_NUM_LEN) + { + return IMGUTIL_PROC_MORE_DATA; + } + + if (!memcmp(imageBuf, magicnum, COMBOIMG_MAGIC_NUM_LEN)) + return IMGUTIL_PROC_FOUND; + else + return IMGUTIL_PROC_NOT_FOUND; +} + + +imgutil_ret_e bcmImg_ComboImageParseHeader(char *imageBuf, UINT32 imageLen, + UINT32 *consumed, UINT32 *image_len, int *parsingState, + Comboimg_header_tag *comboTagP, Comboimg_individual_img_tag *indvTagP, + imgutil_accept_range_ctx_t *ar_ctx) +{ + static Comboimg_header_tag header_tag_tmp, *header_tag_ptr; + static Comboimg_individual_img_tag *image_tag_ptr; + static Comboimg_individual_img_tag image_tag_tmp; + UINT32 i = 0; + + //state variables must get reset + static UINT32 offset_to_image = 0; + static UINT32 stream_location = 0; + static UINT32 header_len = 0; + static char *combo_rcv_buf = 0; + + //todo: fix endianity to support little endian deployment + //todo: what if first packet does not have complete header_tag + // deal with extended header header and image tag + + //printf("in function combo parser\n"); + *consumed = 0; + + while (*consumed < imageLen && combo_parsing_state!=combo_done) + { + switch (combo_parsing_state) + { + case combo_init: + //reset all state variables + stream_location = 0; + offset_to_image = 0; + combo_rcv_buf = 0; + //assuming here that magic_number received in whole + if (bcmImg_ComboImageIdentify(imageBuf, imageLen) != IMGUTIL_PROC_FOUND) + { + combo_parsing_state = not_combo; + *parsingState = combo_parsing_state; + return IMGUTIL_PROC_OK; + } + else + { + comboimg_info("found combo magic number, setting combo parse state: get_header_tag\n"); + combo_parsing_state = get_header_tag; + } + //fall-through + case get_header_tag: + { + //copy just what needed to get header tag + UINT32 need = sizeof(Comboimg_header_tag) - stream_location; + comboimg_debug("in combo parse state get_header_tag, need %d more to combo header tag\n",need); + if (need > imageLen) + { + memcpy(&header_tag_tmp,imageBuf, imageLen); + stream_location += imageLen; + *consumed += imageLen; + } + else + { + comboimg_debug("copying %d bytes to header_tmp for imageBuf\n",need); + memcpy(&header_tag_tmp,imageBuf, need); + stream_location += need; + *consumed += need; + header_len = be32toh(header_tag_tmp.header_len); + comboimg_debug("combo header len: %u, allocating rcvbuf\n",header_len); + + //allocate memory pad, copy it and whatever remaning in imageBuf + //to pad, move state + combo_rcv_buf = calloc(header_len,1); + memcpy(combo_rcv_buf,&header_tag_tmp,sizeof(Comboimg_header_tag)); + //memcpy(combo_rcv_buf + sizeof(Comboimg_header_tag) + // ,imageBuf+need, imageLen-need); + //continue to debug here + comboimg_debug("setting combo parsing state to buffering_complete_header.\n"); + combo_parsing_state = buffering_complete_header; + comboimg_debug("got header_tag.\n"); + comboimg_debug("stream location %d\n",stream_location); + comboimg_debug("consumed %d\n",*consumed); + + header_tag_ptr = (Comboimg_header_tag*)combo_rcv_buf; + + DUMP_HEX(combo_rcv_buf,sizeof(Comboimg_header_tag)); + } + } + break; + case buffering_complete_header: + { + //must fix endian for reverse singular image header + //buffering is required because receiving is not promised to be + //aligned to combo header structure + UINT32 need = header_len - stream_location; + comboimg_debug("in buffering complete header, need %d\n",need); + if (need > imageLen - *consumed) + { + //need to buffer more + memcpy(combo_rcv_buf + stream_location, imageBuf + *consumed + ,imageLen - *consumed); + stream_location += (imageLen - *consumed); + *consumed += (imageLen - *consumed); + } + else + { + memcpy(combo_rcv_buf + stream_location, imageBuf + *consumed + , need); + stream_location += need; + *consumed += need; + + //validate CRC + UINT32 calculated_crc = CRC_INITIAL_VALUE; + UINT32 received_crc = be32toh(header_tag_ptr->header_crc); + + header_tag_ptr->header_crc = 0 ; + DUMP_HEX(combo_rcv_buf, header_len); + calculated_crc = genUtl_getCrc32((unsigned char*)combo_rcv_buf, + header_len , calculated_crc); + + if (calculated_crc != received_crc) + { + comboimg_debug("received CRC is 0x%08X\n", received_crc); + comboimg_debug("calculated CRC is 0x%08X\n", calculated_crc); + combo_parsing_state = fail; + free(combo_rcv_buf); + comboimg_info("Error in combo header CRC\n"); + *parsingState = combo_parsing_state; + return IMGUTIL_PROC_INVALID_IMG; + } + else + comboimg_debug("combo header CRC validated\n"); + + //reverse header endianess + UINT32* curr = 0; + comboimg_debug("flipping header_tag endian\n"); + for (curr = &header_tag_ptr->header_len; + curr <= &header_tag_ptr->extended_combo_header; curr++) + { + *curr = be32toh(*curr); + } + + //todo: flip the extended header TLV entries + + //flip endian for individual image headers + image_tag_ptr = (Comboimg_individual_img_tag*) ( + (char*)&header_tag_ptr->extended_combo_header + + header_tag_ptr->next_tag_offset); + + for (i = 0; i < header_tag_ptr->image_count; i++) + { + UINT32* curr = 0; + + for(curr = &image_tag_ptr->chip_id; + curr <= &image_tag_ptr->extended_image_header; curr++) + { + *curr = be32toh(*curr); + } + //todo: flip the extended header TLV entries + + image_tag_ptr = (Comboimg_individual_img_tag*) ( + (char*)&image_tag_ptr->extended_image_header + + image_tag_ptr->next_tag_offset); + } + + // in case of failue set state and free(combo_rcv_buf); + // must deal with extended header here + combo_parsing_state = in_image; + comboimg_debug("finished buffering combo_header, total received %d\n",stream_location); + comboimg_debug("setting combo parsing state to in_image.\n"); + dump_combo_header_tag(header_tag_ptr); + } + } + break; + case in_image: + image_tag_ptr = (Comboimg_individual_img_tag*) ( + (char*)&header_tag_ptr->extended_combo_header + + header_tag_ptr->next_tag_offset); + + comboimg_info("searching an image for chip: %08X boardid: %s\n", CHIP_FAMILY_ID_HEX, board_id); + for (i = 0; iimage_count; i++) + { + comboimg_debug("image %d\n",i); + dump_individual_image_tag(image_tag_ptr); + DUMP_HEX((char*)image_tag_ptr, sizeof(Comboimg_individual_img_tag)); + //todo: need to consider extended header length + //*consumed += sizeof(Comboimg_individual_img_tag); + if (image_tag_ptr->chip_id == CHIP_FAMILY_ID_HEX + && !strncmp(image_tag_ptr->board_id, board_id, strlen(board_id))) + { + comboimg_info("found chip_id match, calculating offset\n"); + comboimg_debug("value of offset in image header: 0x%08x \n", image_tag_ptr->image_offset); + //could be also image_offset -header length + offset_to_image = image_tag_ptr->image_offset - stream_location; + comboimg_debug("offset to image from current stream location: %u\n", offset_to_image); + *image_len = image_tag_ptr->image_len; + comboimg_debug("image len is: %d\n",*image_len); + memcpy(&image_tag_tmp, image_tag_ptr, sizeof(Comboimg_individual_img_tag)); + memcpy(comboTagP, combo_rcv_buf, sizeof(Comboimg_header_tag)); + memcpy(indvTagP, &image_tag_tmp, sizeof(Comboimg_individual_img_tag)); + + if(!ar_ctx->accept_ranges) + { + comboimg_info("server does not support Accept-Ranges. setting combo parsing state to rolling.\n"); + combo_parsing_state = rolling; + } + else + { + ar_ctx->range_begin = image_tag_ptr->image_offset; + ar_ctx->range_end = ar_ctx->range_begin + image_tag_ptr->image_len - 1; + comboimg_info("Individual image range_begin to %lu range_end %lu\n" + ,ar_ctx->range_begin, ar_ctx->range_end); + combo_parsing_state = combo_done; + //free rcv_buffer_here + free(combo_rcv_buf); + } + break; + } + image_tag_ptr = (Comboimg_individual_img_tag*) ( + (char*)&image_tag_ptr->extended_image_header + image_tag_ptr->next_tag_offset); + //todo: need to consider extended header length + //dataptr += *used; //(char*)&image_tag[i].extended_image_header + image_tag[i].next_tag_offset; + } + if (combo_parsing_state != rolling && combo_parsing_state != combo_done) + { + comboimg_info("didn't find matching image\n"); + combo_parsing_state = fail; + return IMGUTIL_PROC_NOT_FOUND; + } + break; + case rolling: + //comboimg_debug("in rolling, offset %u\n",offset_to_image); + //comboimg_debug("imageLen value: %u\n",imageLen); + //comboimg_debug("consumed value: %u\n",*consumed); + printf("R"); + + if (offset_to_image > imageLen - *consumed) + { + //comboimg_debug("\nimage starts next packets\n"); + offset_to_image -= (imageLen - *consumed); + *consumed += (imageLen - *consumed); + stream_location += (imageLen - *consumed); + } + else + { + comboimg_debug("\nimage starts in this packet, offset to image %u\n",offset_to_image); + *consumed = offset_to_image; + stream_location += offset_to_image; + comboimg_info("\nrolling done. stream_location %d, consumed %d\n",stream_location,*consumed); + combo_parsing_state = combo_done; + //free rcv_buffer_here + free(combo_rcv_buf); + *parsingState = combo_parsing_state; + return IMGUTIL_PROC_OK; + } + break; + } + } + + //comboimg_debug("Exiting combo parsing function. state %d\n", combo_parsing_state); + *parsingState = combo_parsing_state; + return IMGUTIL_PROC_OK; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif.c new file mode 100755 index 00000000000..3bc925ab58a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif.c @@ -0,0 +1,341 @@ +/***************************************************************************** + * <:copyright-BRCM:2015:DUAL/GPL:standard + * + * Copyright (c) 2015 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ****************************************************************************/ + +/***************************************************************************** +* Description: +* +* The BCM CPE software Image Incremental Flashing (imageIf) library +* implementation. This library runs on top of bcm_flashutil. It uses +* the incremental flashing mechanism to avoid holding the entire image +* in RAM, thus reduces RAM usage. +* This library is expected to be platform-independent. The underlying +* bcm_flashutil library handles the platform-specific operations. +* Notes about the library: +* - It supports FLASH format image, with a Whole Flash Image WFI_TAG +* (length TOKEN_LEN) trailer. It supports NAND flash. +* - It assumes CFEROM stays on erase block #0 only. +* - It does not handle BROADCOM format image or NOR flash. +* - It does not handle the configuration file upgrade, and messages +* related to the configuration file validation. +* +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ +#include "bcm_flashutil.h" +#include "bcm_flashutil_nand.h" +#include "bcm_flashutil_emmc.h" +#include "bcm_flashutil_nor.h" +#include "bcm_imgif.h" +#include "bcm_imgif_nand.h" +#include "bcm_imgif_emmc.h" +#include "bcm_imgif_pkgtb.h" + +/* ---- Constants and Types ----------------------------------------------- */ +/* IMGIF context. */ +typedef struct +{ + IMGIF_HANDLE (*imgif_open_cb)(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb); + int (*imgif_write_cb)(IMGIF_HANDLE h, UINT8 *dataP, int len); + int (*imgif_close_cb)(IMGIF_HANDLE h, UBOOL8 abortFlag); + int (*imgif_set_image_info_cb)(IMGIF_HANDLE h, imgif_img_info_t *imgInfoP); + int (*imgif_get_flash_info_cb)(imgif_flash_info_t *flashInfoP); + unsigned int flash_type; +} imgif_ctx_t; + +/* ---- Private Function Prototypes --------------------------------------- */ +/* ---- Public Variables -------------------------------------------------- */ +/* ---- Private Variables ------------------------------------------------- */ +static imgif_ctx_t imgif_ctx = {NULL, NULL, NULL, NULL, NULL, 0}; +/* ---- Functions --------------------------------------------------------- */ + +/***************************************************************************** +* FUNCTION: imgif_init +* PURPOSE: Initialize imgif callbacks. +* PARAMETERS: +* None. +* RETURNS: +* TRUE - supported and enabled. FALSE - else. +* NOTES: +* None. +*****************************************************************************/ +static void imgif_init(void) +{ + /* Ignore redundant calls to this function */ + if( imgif_ctx.flash_type ) + return; + + if( getFlashInfo(&imgif_ctx.flash_type) >= 0 ) + { + switch( imgif_ctx.flash_type ) + { +#ifdef SUPPORT_INCREMENTAL_FLASHING + case FLASH_INFO_FLAG_NAND: + if( nandIsLegacyFlashLayout() ) + { + imgif_ctx.imgif_open_cb = imgif_nand_open; + imgif_ctx.imgif_write_cb = imgif_nand_write; + imgif_ctx.imgif_close_cb = imgif_nand_close; + imgif_ctx.imgif_set_image_info_cb = imgif_nand_set_image_info; + imgif_ctx.imgif_get_flash_info_cb = imgif_nand_get_flash_info; + } + else + { + imgif_ctx.imgif_open_cb = imgif_pkgtb_open; + imgif_ctx.imgif_write_cb = imgif_pkgtb_write; + imgif_ctx.imgif_close_cb = imgif_pkgtb_close; + imgif_ctx.imgif_set_image_info_cb = imgif_pkgtb_set_image_info; + imgif_ctx.imgif_get_flash_info_cb = imgif_pkgtb_get_flash_info; + } + printf("imgif: Enabling NAND incremental flashing functions!\n"); + break; + + case FLASH_INFO_FLAG_EMMC: + if( emmcIsLegacyFlashLayout() ) + { + imgif_ctx.imgif_open_cb = imgif_emmc_open; + imgif_ctx.imgif_write_cb = imgif_emmc_write; + imgif_ctx.imgif_close_cb = imgif_emmc_close; + imgif_ctx.imgif_set_image_info_cb = imgif_emmc_set_image_info; + imgif_ctx.imgif_get_flash_info_cb = imgif_emmc_get_flash_info; + } + else + { + imgif_ctx.imgif_open_cb = imgif_pkgtb_open; + imgif_ctx.imgif_write_cb = imgif_pkgtb_write; + imgif_ctx.imgif_close_cb = imgif_pkgtb_close; + imgif_ctx.imgif_set_image_info_cb = imgif_pkgtb_set_image_info; + imgif_ctx.imgif_get_flash_info_cb = imgif_pkgtb_get_flash_info; + } + printf("imgif: Enabling EMMC incremental flashing functions!\n"); + break; + +#ifndef DESKTOP_LINUX + case FLASH_INFO_FLAG_NOR: + if( norIsNewFlashLayout() ) + { + imgif_ctx.imgif_open_cb = imgif_pkgtb_open; + imgif_ctx.imgif_write_cb = imgif_pkgtb_write; + imgif_ctx.imgif_close_cb = imgif_pkgtb_close; + imgif_ctx.imgif_set_image_info_cb = imgif_pkgtb_set_image_info; + imgif_ctx.imgif_get_flash_info_cb = imgif_pkgtb_get_flash_info; + printf("imgif: Enabling SPI NOR incremental flashing functions!\n"); + } + else + printf("imgif: Incremental flashing not supported!\n"); + break; +#endif +#endif + default: + printf("imgif: Incremental flashing not supported!\n"); + break; + } + } + else + { + printf("imgif: Error! Cannot determine flash type!\n"); + } + +} + + +/***************************************************************************** +* FUNCTION: imgif_open +* PURPOSE: Initialize IMGIF context. +* PARAMETERS: +* fmtParserCb (IN) Image parser callback function. + calCrc32Cb (IN) Application-specific CRC algorithm callback function. +* RETURNS: +* Pointer to the IMGIF context - successful operation. +* NULL - failed operation, for example, another software upgrade already +* in progress. +* NOTES: +* None. +*****************************************************************************/ +IMGIF_HANDLE imgif_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb) +{ + if( !imgif_ctx.flash_type ) + imgif_init(); + + if( imgif_ctx.imgif_open_cb ) + return (imgif_ctx.imgif_open_cb( fmtParserCb, calCrc32Cb)); + else + { + printf("imgif: Error! imgif not initialized!\n"); + return(NULL); + } +} + +/***************************************************************************** +* FUNCTION: imgif_write +* PURPOSE: Write image block to IMGIF. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* dataP (IN) - image block data pointer. +* len (IN) - image block size. +* RETURNS: +* >=0 - number of bytes written. +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +int imgif_write(IMGIF_HANDLE h, UINT8 *dataP, int len) +{ + if( imgif_ctx.imgif_write_cb ) + return (imgif_ctx.imgif_write_cb( h, dataP, len )); + else + { + printf("imgif: Error! imgif not initialized!\n"); + return(-1); + } +} + +/***************************************************************************** +* FUNCTION: imgif_close +* PURPOSE: Close IMGIF context. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* abortFlag (IN) - TRUE: user aborts the operation. +* RETURNS: +* 0 - successful operation. +* -1 - failed operation. +* NOTES: +* User may stop an upgrade at any time, when there is an operator, +* command, protocol failure, or unmatched image size and/or CRC values +* between IMGIF and user. +*****************************************************************************/ +int imgif_close(IMGIF_HANDLE h, UBOOL8 abortFlag) +{ + if( imgif_ctx.imgif_close_cb ) + return (imgif_ctx.imgif_close_cb( h, abortFlag )); + else + { + printf("imgif: Error! imgif not initialized!\n"); + return(-1); + } +} + +/***************************************************************************** +* FUNCTION: imgif_set_image_info +* PURPOSE: Set image info obtained externally. +* PARAMETERS: + h (IN) - IMGIF context pointer. + imgInfoExtP (OUT) - image info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. However, it is typically +* invoked at the end of the upgrade, when user has received the whole +* image, and has obtained the image integrity information. +*****************************************************************************/ +int imgif_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoExtP) +{ + if( !imgif_ctx.flash_type ) + imgif_init(); + + if( imgif_ctx.imgif_set_image_info_cb ) + return (imgif_ctx.imgif_set_image_info_cb( h, imgInfoExtP )); + else + { + printf("imgif: Error! imgif not initialized!\n"); + return(-1); + } +} + +/***************************************************************************** +* FUNCTION: imgif_get_flash_info +* PURPOSE: Obtain flash info. +* PARAMETERS: + h (IN) - IMGIF context pointer. + flashInfoP (OUT) - flash info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. +*****************************************************************************/ +int imgif_get_flash_info(imgif_flash_info_t *flashInfoP) +{ + if( !imgif_ctx.flash_type ) + imgif_init(); + + if( imgif_ctx.imgif_get_flash_info_cb ) + return (imgif_ctx.imgif_get_flash_info_cb( flashInfoP )); + else + { + printf("imgif: Error! imgif not initialized!\n"); + return(-1); + } +} + +/***************************************************************************** +* FUNCTION: imgif_get_enable_mode +* PURPOSE: Check whether incremental flashing is supported and enabled. +* PARAMETERS: +* None. +* RETURNS: +* TRUE - supported and enabled. FALSE - else. +* NOTES: +* None. +*****************************************************************************/ +UBOOL8 imgif_get_enable_mode(void) +{ + UBOOL8 mode = FALSE; + + if( !imgif_ctx.flash_type ) + imgif_init(); + + switch( imgif_ctx.flash_type ) + { + case FLASH_INFO_FLAG_NAND: + case FLASH_INFO_FLAG_EMMC: +#ifdef SUPPORT_INCREMENTAL_FLASHING + mode = TRUE; +#endif /* SUPPORT_INCREMENTAL_FLASHING */ + break; + + case FLASH_INFO_FLAG_NOR: +#ifdef SUPPORT_INCREMENTAL_FLASHING +#ifndef DESKTOP_LINUX + + if (norIsNewFlashLayout()) + mode = TRUE; +#endif +#endif /* SUPPORT_INCREMENTAL_FLASHING */ + break; + default: + mode = FALSE; + break; + } + + return mode; +} + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_emmc.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_emmc.c new file mode 100755 index 00000000000..5c1a2885a01 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_emmc.c @@ -0,0 +1,881 @@ +/***************************************************************************** + * <:copyright-BRCM:2015:DUAL/GPL:standard + * + * Copyright (c) 2015 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ****************************************************************************/ + +/***************************************************************************** +* Description: +* +* The BCM CPE software Image Incremental Flashing (imageIf) library +* implementation. This library runs on top of bcm_flashutil. It uses +* the incremental flashing mechanism to avoid holding the entire image +* in RAM, thus reduces RAM usage. +* This library is expected to be platform-independent. The underlying +* bcm_flashutil library handles the platform-specific operations. +* Notes about the library: +* +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ +#include "bcm_flashutil.h" +#include "bcm_flashutil_emmc.h" +#include "bcm_imgif.h" +#include "bcm_imgif_emmc.h" +#include "bcmTag.h" +#include "bcm_hwdefs.h" +#include "bcm_boarddriverctl.h" +#include "emmc_linux_defs.h" +#include "genutil_crc.h" + +/* ---- Constants and Types ----------------------------------------------- */ +#define IMG_WRITE_FS 1 /* Keep enabled: Enable filesystem writing */ +#define IMG_WRITE_NVRAM 0 /* Keep disabled: Image update does NOT modify NVRAM */ +#define CC_IMGIF_DEBUG 0 + +/* Must assume an order to the parts for this to work + * TAG, cferom, roots, bootfs, metadata */ +typedef enum +{ + IMGIF_EMMC_IMG_SEGMENT_TAG = 0, + IMGIF_EMMC_IMG_SEGMENT_CFEROM, + IMGIF_EMMC_IMG_SEGMENT_ROOTFS, + IMGIF_EMMC_IMG_SEGMENT_BOOTFS, + IMGIF_EMMC_IMG_SEGMENT_MDATA, + IMGIF_EMMC_IMG_SEGMENT_MAX +} IMGIF_EMMC_IMG_SEGMENTS; + +typedef struct +{ + unsigned int flash_offset; + unsigned int size; + unsigned int bytesdone; +} IMGIF_EMMC_IMG_SEGMENT_INFO; + +/* IMGIF emmc context. */ +typedef struct +{ +#if IMG_WRITE_NVRAM + FILE * nvram_fh; +#endif + FILE * cferom_fh; + FILE * rootfs_fh; + FILE * bootfs_fh; + FILE * mdata_primary_fh; + FILE * mdata_backup_fh; + IMGIF_EMMC_IMG_SEGMENT_INFO emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MAX]; + IMGIF_EMMC_IMG_SEGMENTS current_img_segment; + unsigned int crc_body_exp; + unsigned int crc_body_calc; + unsigned int crc_image_calc; + unsigned int image_size_calc; + char * mdata_ptr; + char * cferom_ptr; + int bootp_seqnum; + int updatep_seqnum; + int booted_partition; + int update_partition; + FILE_TAG tag; + + imgif_img_info_t imgInfoExt; + + IMG_FORMAT_PARSER_CB fmtParserCb; + CAL_CRC32_CB calCrc32Cb; +} imgif_ctx_t; + +#define getCtx() (&imgif_ctx) +#define getCtxByHandle(h) ((imgif_ctx_t*)h) + +#if CC_IMGIF_DEBUG +#define imgif_debug(fmt, arg...) \ + printf("%s.%u: " fmt , __FUNCTION__, __LINE__, ##arg) +#define DUMPIMGIFCTX(cxtP) dump_ctx(ctxP) +#else +#define imgif_debug(fmt, arg...) +#define DUMPIMGIFCTX(cxtP) +#endif + +#define imgif_error(fmt, arg...) \ + printf("ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + +/* ---- Private Function Prototypes --------------------------------------- */ +/* ---- Public Variables -------------------------------------------------- */ +/* ---- Private Variables ------------------------------------------------- */ +static imgif_ctx_t imgif_ctx; +/* ---- Functions --------------------------------------------------------- */ + +static void print_imgupdate_progress( imgif_ctx_t * ctxP) +{ +#if CC_IMGIF_DEBUG + int i = 0; + int size = 0; + int bytes_done = 0; + + for( i=0; iemmc_img_segments[i].size; + bytes_done += ctxP->emmc_img_segments[i].bytesdone; + } + printf("\rImage Update Progress: %d/%d bytes\n", bytes_done, size); +#else + fprintf(stderr, "."); +#endif +} + +/***************************************************************************** +* FUNCTION: process_image_tag +* PURPOSE: process a complete broadcom image tag +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* pTag (IN) - Broadcom image tag. +* RETURNS: +* -1 - failed operation. +* NOTES: +* This function does the bulk of resource allocation for emmc img writes. +*****************************************************************************/ +static int process_image_tag( imgif_ctx_t *ctxP, PFILE_TAG pTag ) +{ + int ret = -1; + char mdata_dev_name_rootfs[] = EMMC_DEV_PNAME_FMT_STR_ROOTFS; + char mdata_dev_name_bootfs[] = EMMC_DEV_PNAME_FMT_STR_BOOTFS; + char mdata_dev_name_primary[] = EMMC_DEV_PNAME_FMT_STR_MDATA; + char mdata_dev_name_backup[] = EMMC_DEV_PNAME_FMT_STR_MDATA; + UINT32 * crc_ptr = (UINT32*)(pTag->imageValidationToken); + + /* Dump image tag */ + imgif_debug("--------------------Broadcom image tag------------------------\n"); + imgif_debug("tagVersion: %02x %02x %02x %02x\n", + pTag->tagVersion[0], pTag->tagVersion[1], + pTag->tagVersion[2], pTag->tagVersion[3]); + imgif_debug("endian: %s\n", pTag->bigEndian); + imgif_debug("totalImageLen: %s\n", pTag->totalImageLen); + imgif_debug("cfeAddress: %s\n", pTag->cfeAddress); + imgif_debug("cfeLen: %s\n", pTag->cfeLen); + imgif_debug("rootfsAddress: %s\n", pTag->rootfsAddress); + imgif_debug("rootfsLen: %s\n", pTag->rootfsLen); + imgif_debug("kernelAddress: %s\n", pTag->bootfsAddress); + imgif_debug("kernelLen: %s\n", pTag->bootfsLen); + imgif_debug("mdataAddress: %s\n", pTag->mdataAddress); + imgif_debug("mdataLen: %s\n", pTag->mdataLen); + imgif_debug("imageSequence: %s\n", pTag->imageSequence); + imgif_debug("imageVersion: %s\n", pTag->imageVersion); + imgif_debug("imageFlags: 0x%08x\n", pTag->imageFlags); + imgif_debug("imageCrc: 0x%08x\n", *crc_ptr); + imgif_debug("--------------------------------------------------------------\n"); + + if( atoi(pTag->cfeLen) ) + { + if( emmcVerifyImageDDRType(pTag->imageFlags) ) + return ret; + } + + /* Initialize emmc image segment data */ + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_CFEROM].size = atoi(pTag->cfeLen); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_CFEROM].flash_offset = atoi(pTag->cfeAddress); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_ROOTFS].size = atoi(pTag->rootfsLen); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_ROOTFS].flash_offset = atoi(pTag->rootfsAddress); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_BOOTFS].size = atoi(pTag->bootfsLen); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_BOOTFS].flash_offset = atoi(pTag->bootfsAddress); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MDATA].size = atoi(pTag->mdataLen); + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MDATA].flash_offset = atoi(pTag->mdataAddress); + + /* Store expected image content crc */ + ctxP->crc_body_exp = *crc_ptr; + + /* Allocated memory for temp storage */ + ctxP->mdata_ptr = malloc(atoi(pTag->mdataLen)); + if( atoi(pTag->cfeLen)) + ctxP->cferom_ptr = malloc(atoi(pTag->cfeLen)); + if( !ctxP->mdata_ptr + || (atoi(pTag->cfeLen) && !ctxP->cferom_ptr) ) + { + printf("%s: Error allocating memory for temp storage!\n", __FUNCTION__); + return ret; + } + /* Generate full pathnames for bootfs and rootfs devs */ + sprintf(mdata_dev_name_rootfs, EMMC_DEV_PNAME_FMT_STR_ROOTFS, ctxP->update_partition); + sprintf(mdata_dev_name_bootfs, EMMC_DEV_PNAME_FMT_STR_BOOTFS, ctxP->update_partition); + + /* Generate full pathnames for metadata devs */ + sprintf(mdata_dev_name_primary, EMMC_DEV_PNAME_FMT_STR_MDATA, ctxP->update_partition, + EMMC_IMG_IDX_START); + sprintf(mdata_dev_name_backup, EMMC_DEV_PNAME_FMT_STR_MDATA, ctxP->update_partition, + EMMC_NUM_MDATA); + +#if IMG_WRITE_FS + /* Open cferom and nvram devices */ + if( atoi(pTag->cfeLen) ) + { +#if IMG_WRITE_NVRAM + ctxP->nvram_fh = fopen(EMMC_DEV_PNAME_NVRAM, "r+"); + imgif_debug("Opening file %s for writing\n", EMMC_DEV_PNAME_NVRAM); +#endif + ctxP->cferom_fh = fopen(EMMC_DEV_PNAME_CFE, "r+"); + imgif_debug("Opening file %s for writing\n", EMMC_DEV_PNAME_CFE); + } + + /* Open rootfs, bootfs, and metadata devices */ + imgif_debug("Opening file %s for writing\n", mdata_dev_name_rootfs); + imgif_debug("Opening file %s for writing\n", mdata_dev_name_bootfs); + imgif_debug("Opening file %s for writing\n", mdata_dev_name_primary); + imgif_debug("Opening file %s for writing\n", mdata_dev_name_backup); + ctxP->rootfs_fh = fopen(mdata_dev_name_rootfs, "r+"); + ctxP->bootfs_fh = fopen(mdata_dev_name_bootfs, "r+"); + ctxP->mdata_primary_fh = fopen(mdata_dev_name_primary, "r+"); + ctxP->mdata_backup_fh = fopen(mdata_dev_name_backup, "r+"); + + if( (atoi(pTag->cfeLen) && !ctxP->cferom_fh) +#if IMG_WRITE_NVRAM + || (atoi(pTag->cfeLen) && !ctxP->nvram_fh) +#endif + || !ctxP->rootfs_fh + || !ctxP->bootfs_fh + || !ctxP->mdata_primary_fh + || !ctxP->mdata_backup_fh ) + { + printf("%s: Failed to open emmc devices!\n", __FUNCTION__); + ret = -1; + } + else + ret = 0; +#else + ret = 0; +#endif /* IMG_WRITE_FS */ + + return ret; +} + +/***************************************************************************** +* FUNCTION: init_ctx +* PURPOSE: initialize emmc img write parameters +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int init_ctx(imgif_ctx_t *ctxP) +{ + int ret = -1; + + /* Initialize image segment values */ + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_TAG].size = TAG_LEN; + ctxP->current_img_segment = IMGIF_EMMC_IMG_SEGMENT_TAG; + + /* Initialize whole image crc */ + if (ctxP->calCrc32Cb != NULL) + ctxP->calCrc32Cb(0, &ctxP->crc_image_calc, NULL, 0); + + /* Initialize image contents crc */ + genUtl_getCrc32Staged(0, &ctxP->crc_body_calc, NULL, 0); + + /* Initialize image size */ + ctxP->image_size_calc = 0; + + /* Get booted and update partition numbers */ + ret = emmcGetBootPartition(); + if( ret == -1 ) + { + printf("%s: Error while retrieving boot partition number!\n", __FUNCTION__); + return ret; + } + else + { + ctxP->booted_partition = ret; + ctxP->update_partition = + (ctxP->booted_partition==EMMC_IMG_IDX_START)?EMMC_NUM_IMGS:EMMC_IMG_IDX_START; + } + + /* Get sequence numbers */ + ctxP->bootp_seqnum = getSequenceNumber(ctxP->booted_partition); + ctxP->updatep_seqnum = getSequenceNumber(ctxP->update_partition); + return 0; +} + +/***************************************************************************** +* FUNCTION: deinit_ctx +* PURPOSE: free all emmc image write related resources +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int deinit_ctx(imgif_ctx_t *ctxP) +{ + imgif_debug("Closing all files\n"); +#if IMG_WRITE_FS + /* Close all open files */ +#if IMG_WRITE_NVRAM + if(ctxP->nvram_fh) + fclose(ctxP->nvram_fh); +#endif + if(ctxP->cferom_fh) + fclose(ctxP->cferom_fh); + fclose(ctxP->rootfs_fh); + fclose(ctxP->bootfs_fh); + fclose(ctxP->mdata_primary_fh); + fclose(ctxP->mdata_backup_fh); +#endif + + imgif_debug("Freeing all allocated memory\n"); + + /* Free allocated memory */ + if( ctxP->cferom_ptr ) + free(ctxP->cferom_ptr); + + if( ctxP->mdata_ptr ) + free(ctxP->mdata_ptr); + + return 0; +} + +/***************************************************************************** +* FUNCTION: write_bytes_to_emmc_device +* PURPOSE: write bytes to emmc devices +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* data (IN) - data pointer +* num_bytes (IN) - number of bytes to write +* RETURNS: +* >0 - number of bytes written +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int write_bytes_to_emmc_device( imgif_ctx_t *ctxP, char * data, unsigned int num_bytes ) +{ + int bytes_left, bytes_to_write; + int written_bytes = 0; + char * datap = data; + char * dest_ptr = NULL; + FILE * dest_fh = NULL; + + imgif_debug("num_bytes:%d\n", num_bytes); + + while( num_bytes ) + { + /* If all image data segments have have been written, but we still need to write more bytes + * , this means that image may be corrupted (may possibly happen if there is extra padding added + * to end of file). In this case we dont write the extra bytes and simply return with a invalid crc + */ + if( ctxP->current_img_segment == IMGIF_EMMC_IMG_SEGMENT_MAX ) + { + /* Clear CRC calc to indicate failiure */ + ctxP->crc_body_calc = 0; + printf("%s: Error: Attempt to write %d unknown img data bytes to invalid segment %d!\n", + __FUNCTION__, num_bytes, ctxP->current_img_segment); + return -1; + } + + /* Start processing writes */ + imgif_debug("Segment:%d, segment size:%d, bytes_done:%d, currwrite:%d\n", + ctxP->current_img_segment, + ctxP->emmc_img_segments[ctxP->current_img_segment].size, + ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone, + num_bytes); + + /* Calculate how many bytes left to copy for segment */ + bytes_left = ctxP->emmc_img_segments[ctxP->current_img_segment].size + - ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone; + + /* Calculate how many bytes we can actually write */ + bytes_to_write = (bytes_left <= num_bytes)? bytes_left:num_bytes; + + /* Figure out whether we need to cache the segment data in memory or write it to fs */ + switch(ctxP->current_img_segment) + { + case IMGIF_EMMC_IMG_SEGMENT_TAG: + /* Copy to local buffer */ + dest_ptr = (char*)&ctxP->tag; + break; + + case IMGIF_EMMC_IMG_SEGMENT_CFEROM: + /* write to local cferom */ + dest_ptr = ctxP->cferom_ptr; + break; + + case IMGIF_EMMC_IMG_SEGMENT_MDATA: + /* write to local metadata */ + dest_ptr = ctxP->mdata_ptr; + break; + + case IMGIF_EMMC_IMG_SEGMENT_ROOTFS: + dest_fh = ctxP->rootfs_fh; + break; + + case IMGIF_EMMC_IMG_SEGMENT_BOOTFS: + dest_fh = ctxP->bootfs_fh; + break; + + default: + printf("%s: Invalid segment! %d\n", __FUNCTION__, ctxP->current_img_segment); + return -1; + break; + } + + /* Write data to either local memory or to filesystem */ + if( dest_ptr ) + { + imgif_debug("Writing %d bytes to ptr:0x%08x\n", bytes_to_write, + (unsigned int)(dest_ptr + + ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone)); + memcpy(dest_ptr + ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone, + datap, bytes_to_write); + dest_ptr = NULL; + } + else if( dest_fh ) + { +#if IMG_WRITE_FS + imgif_debug("Writing %d bytes to file:0x%08x\n", bytes_to_write, + (unsigned int)(dest_fh)); + fwrite(datap, 1, bytes_to_write, dest_fh); + if( ferror(dest_fh) || feof(dest_fh) ) + { + printf("%s: Error writing segment %d\n", + __FUNCTION__, + ctxP->current_img_segment); + return -1; + } + dest_fh = NULL; +#endif + } + + /* Do whole image crc on all data */ + if (ctxP->calCrc32Cb != NULL) + ctxP->calCrc32Cb(1, &ctxP->crc_image_calc, (unsigned char*)datap, bytes_to_write); + + /* Do content crc on non-tag data */ + if( ctxP->current_img_segment != IMGIF_EMMC_IMG_SEGMENT_TAG ) + genUtl_getCrc32Staged(1, &ctxP->crc_body_calc, (unsigned char*)datap, bytes_to_write); + + imgif_debug("crc img tally:0x%08x\n", ctxP->crc_image_calc); + imgif_debug("crc body tally:0x%08x\n", ctxP->crc_body_calc); + + /* Increment bytes done, advance data pointer and adjust remaining bytes */ + ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone += bytes_to_write; + datap += bytes_to_write; + num_bytes -= bytes_to_write; + written_bytes += bytes_to_write; + ctxP->image_size_calc += bytes_to_write; + + imgif_debug("written_bytes:%d\n", written_bytes); + imgif_debug("bytes left: current_write:%d segment:%d\n", num_bytes, + ctxP->emmc_img_segments[ctxP->current_img_segment].size - + ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone); + + /* Move to next segment if current segment is done */ + if( ctxP->emmc_img_segments[ctxP->current_img_segment].bytesdone == + ctxP->emmc_img_segments[ctxP->current_img_segment].size ) + { + /* If we have the full image tag, process its contents */ + if( ctxP->current_img_segment == IMGIF_EMMC_IMG_SEGMENT_TAG ) + { + if( process_image_tag(ctxP, &ctxP->tag) == -1 ) + return -1; + } + + /* Increment to next valid segment */ + while( ctxP->current_img_segment < IMGIF_EMMC_IMG_SEGMENT_MAX ) + { + ctxP->current_img_segment++; + imgif_debug("segment change:%d->%d\n", ctxP->current_img_segment-1, ctxP->current_img_segment); + + /* Break out if valid segment is detected */ + if( (ctxP->current_img_segment < IMGIF_EMMC_IMG_SEGMENT_MAX) && + ctxP->emmc_img_segments[ctxP->current_img_segment].size ) + break; + } + + } + imgif_debug("\n"); + } + print_imgupdate_progress(ctxP); + return written_bytes; +} + +#if CC_IMGIF_DEBUG +/***************************************************************************** +* FUNCTION: dump_ctx +* PURPOSE: dump all emmc img write related parameters. +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* NOTES: +* None. +*****************************************************************************/ +static void dump_ctx(imgif_ctx_t *ctxP) +{ + int i = 0; + imgif_debug("------------------------imgif_emmc ctx------------------------------\n"); + for( i=0; iemmc_img_segments[i].flash_offset, + ctxP->emmc_img_segments[i].size, + ctxP->emmc_img_segments[i].bytesdone); + } + imgif_debug("crc_image_calc 0x%08x crc_image_exp 0x%08x\n", ctxP->crc_image_calc, ctxP->imgInfoExt.crc); + imgif_debug("crc_body_calc 0x%08x crc_body_exp 0x%08x\n", ctxP->crc_body_calc, ctxP->crc_body_exp); + imgif_debug("boot_partition : %d\n", ctxP->booted_partition); + imgif_debug("update_partition : %d\n", ctxP->update_partition); + imgif_debug("boot_partition_seq : %d\n", ctxP->bootp_seqnum); + imgif_debug("update_partition_seq : %d\n", ctxP->updatep_seqnum); + imgif_debug("--------------------------------------------------------------------\n"); +} +#endif + +#if IMG_WRITE_NVRAM +/***************************************************************************** +* FUNCTION: flash_nvram_data +* PURPOSE: Write data to emmc nvram device +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* -1 - failed operation. +* NOTES: +* We dont update the nvram during webgui image updates. Keep this function +* disabled +*****************************************************************************/ +static int flash_nvram_data( imgif_ctx_t *ctxP ) +{ + int ret = -1 + NVRAM_DATA * nvram_ptr; + + /* Handle NVRAM update */ + if( ctxP->cferom_ptr ) + { + nvram_ptr = (NVRAM_DATA *)(ctxP->cferom_ptr + emmcGetNvramOffset((char*)(ctxP->cferom_ptr))); + +#if IMG_WRITE_FS + fwrite((char*)nvram_ptr, 1, + sizeof(NVRAM_DATA), + ctxP->nvram_fh); + + if( ferror(ctxP->nvram_fh) + || feof(ctxP->nvram_fh) ) + { + printf("%s: Error writing NVRAM\n", + __FUNCTION__); + } + else + ret = 0; +#endif + } + else + { + printf("%s: Error writing NVRAM, invalid cferom_ptr\n", + __FUNCTION__); + } + + return ret; +} +#endif /* IMG_WRITE_NVRAM */ + +/***************************************************************************** +* FUNCTION: finalize_emmc_img_write +* PURPOSE: Finalize all write operations. +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* abortFlag (IN) - flag indicating early abort. +* RETURNS: +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int finalize_emmc_img_write(imgif_ctx_t *ctxP, UBOOL8 abortFlag) +{ + int ret = -1; + + if( abortFlag ) + goto cleanup; + + /* Check if the whole image CRC matched */ + if((ctxP->calCrc32Cb != NULL) && (ctxP->imgInfoExt.bitmask & IMG_INFO_BITMASK_CRC)) + { + ctxP->calCrc32Cb(2, &ctxP->crc_image_calc, NULL, 0); + + if( ctxP->crc_image_calc != ctxP->imgInfoExt.crc ) + { + printf("%s: Whole Image CRC check failed! expected:0x%08x, calculated:0x%08x\n", + __FUNCTION__, + ctxP->imgInfoExt.crc, + ctxP->crc_image_calc); + goto cleanup; + } + } + + /* Check if size matched */ + if ((ctxP->imgInfoExt.bitmask & IMG_INFO_BITMASK_SIZE) && (ctxP->imgInfoExt.size != ctxP->image_size_calc)) + { + printf("Unmatched file size values, ext=0x%08x, cal=0x%08x", + ctxP->imgInfoExt.size, ctxP->image_size_calc); + goto cleanup;; + } + + /* Check if image contents CRC matched expected value */ + if( ctxP->crc_body_calc == ctxP->crc_body_exp ) + { +#if IMG_WRITE_FS + unsigned int seq_num; + + /* Write cferom to partition */ + if ( ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_CFEROM].bytesdone ) + { + /* Enable write access to emmc physical boot partition */ + imgif_debug("cfe partition unlock command: %s\n", EMMC_BOOT_PARTITION_UNLOCK_CMD); + system(EMMC_BOOT_PARTITION_UNLOCK_CMD); + + /* Seek to specified offset in partition and write cferom data */ + imgif_debug("Setting cferom file pointer to offset 0x%08x\n", IMAGE_OFFSET); + if(fseek(ctxP->cferom_fh, IMAGE_OFFSET, SEEK_SET) != 0) + { + printf("%s: Error during cferom fseek\n", __FUNCTION__); + goto cleanup; + } + + /* Write cferom data */ + imgif_debug("Writing %d bytes of cferom to file:0x%08x\n", + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_CFEROM].bytesdone, + (unsigned int)(ctxP->cferom_fh)); + fwrite(ctxP->cferom_ptr, 1, + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_CFEROM].bytesdone, + ctxP->cferom_fh); + + if( ferror(ctxP->cferom_fh) + || feof(ctxP->cferom_fh) ) + { + printf("%s: Error writing segment %d\n", + __FUNCTION__, + IMGIF_EMMC_IMG_SEGMENT_CFEROM); + goto cleanup; + } + +#if IMG_WRITE_NVRAM + if( flash_nvram_data( ctxP ) == -1 ) + goto cleanup; +#endif + } + + /* Calculate new sequence number */ + imgif_debug("Old sequence numbers %d %d\n", ctxP->bootp_seqnum, ctxP->updatep_seqnum); + seq_num = getNextSequenceNumber(ctxP->bootp_seqnum, ctxP->updatep_seqnum); + + /* Update inmemory copy of mdata with new sequence number */ + imgif_debug("Updating to new sequence number %d\n", seq_num); + if( emmcUpdateMdataSeqnum(ctxP->mdata_ptr, 0, seq_num) == -1 ) + { + printf("%s: Error updating metadata squence number\n", __FUNCTION__); + goto cleanup; + } + + /* Update inmemory copy of mdata with valid commit flag */ + imgif_debug("Updating commit flag\n"); + if( emmcUpdateMdataCommitFlag(ctxP->mdata_ptr, 0, 1) == -1 ) + { + printf("%s: Error updating metadata commit flag\n", __FUNCTION__); + goto cleanup; + } + + /* Write primary metadata to partition */ + imgif_debug("Writing %d bytes of primary mdata to file:0x%08x\n", + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MDATA].bytesdone, + (unsigned int)(ctxP->mdata_primary_fh)); + fwrite(ctxP->mdata_ptr, 1, + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MDATA].bytesdone, + ctxP->mdata_primary_fh); + + /* Write backup metadata to partition */ + imgif_debug("Writing %d bytes of backup mdata to file:0x%08x\n", + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MDATA].bytesdone, + (unsigned int)(ctxP->mdata_backup_fh)); + fwrite(ctxP->mdata_ptr, 1, + ctxP->emmc_img_segments[IMGIF_EMMC_IMG_SEGMENT_MDATA].bytesdone, + ctxP->mdata_backup_fh); + + if( ferror(ctxP->mdata_primary_fh) + || feof(ctxP->mdata_primary_fh) + ||ferror(ctxP->mdata_backup_fh) + || feof(ctxP->mdata_backup_fh) ) + { + printf("%s: Error writing segment %d\n", + __FUNCTION__, + IMGIF_EMMC_IMG_SEGMENT_MDATA); + goto cleanup; + } +#endif + ret = 0; + } + else + { + printf("%s: Image contents CRC check failed! expected:0x%08x, calculated:0x%08x\n", + __FUNCTION__, + ctxP->crc_body_exp, + ctxP->crc_body_calc); + + ret = -1; + } + +cleanup: + /* deinitialize context */ + deinit_ctx(ctxP); + + return ret; +} + +/***************************************************************************** +* FUNCTION: imgif_emmc_open +* PURPOSE: Initialize IMGIF context. +* PARAMETERS: +* fmtParserCb (IN) Image parser callback function. + calCrc32Cb (IN) Application-specific CRC algorithm callback function. +* RETURNS: +* Pointer to the IMGIF context - successful operation. +* NULL - failed operation, for example, another software upgrade already +* in progress. +* NOTES: +* None. +*****************************************************************************/ +IMGIF_HANDLE imgif_emmc_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb) +{ + imgif_ctx_t *ctxP; + ctxP = getCtx(); + memset(ctxP, 0, sizeof(imgif_ctx_t)); + + /* Assign callbacks */ + ctxP->fmtParserCb = fmtParserCb; + ctxP->calCrc32Cb = calCrc32Cb; + + /* Initialize context */ + if( init_ctx(ctxP) == -1 ) + return NULL; + + return((IMGIF_HANDLE)ctxP); +} + +/***************************************************************************** +* FUNCTION: imgif_emmc_write +* PURPOSE: Write image block to IMGIF. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* dataP (IN) - image block data pointer. +* len (IN) - image block size. +* RETURNS: +* >=0 - number of bytes written. +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +int imgif_emmc_write(IMGIF_HANDLE h, UINT8 *dataP, int len) +{ + imgif_ctx_t *ctxP = getCtxByHandle(h); + return(write_bytes_to_emmc_device( ctxP, (char*)dataP, len)); +} + +/***************************************************************************** +* FUNCTION: imgif_emmc_close +* PURPOSE: Close IMGIF context. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* abortFlag (IN) - TRUE: user aborts the operation. +* RETURNS: +* 0 - successful operation. +* -1 - failed operation. +* NOTES: +* User may stop an upgrade at any time, when there is an operator, +* command, protocol failure, or unmatched image size and/or CRC values +* between IMGIF and user. +*****************************************************************************/ +int imgif_emmc_close(IMGIF_HANDLE h, UBOOL8 abortFlag) +{ + imgif_ctx_t *ctxP = getCtxByHandle(h); + DUMPIMGIFCTX(ctxP); + return(finalize_emmc_img_write(ctxP, abortFlag)); +} + +/***************************************************************************** +* FUNCTION: imgif_emmc_set_image_info +* PURPOSE: Set image info obtained externally. +* PARAMETERS: + h (IN) - IMGIF context pointer. + imgInfoExtP (OUT) - image info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. However, it is typically +* invoked at the end of the upgrade, when user has received the whole +* image, and has obtained the image integrity information. +*****************************************************************************/ +int imgif_emmc_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoExtP) +{ + imgif_ctx_t *ctxP = getCtxByHandle(h); + + if ((ctxP != NULL) && (imgInfoExtP != NULL)) + { + ctxP->imgInfoExt.bitmask = imgInfoExtP->bitmask; + ctxP->imgInfoExt.size = imgInfoExtP->size; + ctxP->imgInfoExt.crc = imgInfoExtP->crc; + return 0; + } + + return -1; +} + +/***************************************************************************** +* FUNCTION: imgif_emmc_get_flash_info +* PURPOSE: Obtain flash info. +* PARAMETERS: + h (IN) - IMGIF context pointer. + flashInfoP (OUT) - flash info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. +*****************************************************************************/ +int imgif_emmc_get_flash_info(imgif_flash_info_t *flashInfoP) +{ + int ret = -1; + unsigned int flags; + UINT32 flashSize=0; + ret = getFlashInfo(&flags); + if( ret == 0 ) + { + flashInfoP->flashType = flags; + flashInfoP->eraseSize = 0; + ret = devCtl_boardIoctl(BOARD_IOCTL_FLASH_READ, + FLASH_SIZE, + 0, 0, 0, &flashSize); + if( ret == 0 ) + flashInfoP->flashSize = flashSize; + } + + return(0); +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_emmc.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_emmc.h new file mode 100644 index 00000000000..0f813b8bc10 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_emmc.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * + * Copyright (c) 2015 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2015:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * + ****************************************************************************/ + +#ifndef BCM_IMGIF_EMMC_H +#define BCM_IMGIF_EMMC_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include "bcm_imgif.h" + +/* ---- Constants and Types ----------------------------------------------- */ +/* ---- Variable Externs -------------------------------------------------- */ +/* ---- Function Prototypes ----------------------------------------------- */ + +IMGIF_HANDLE imgif_emmc_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb); +int imgif_emmc_write(IMGIF_HANDLE h, UINT8 *dataP, int len); +int imgif_emmc_close(IMGIF_HANDLE h, UBOOL8 abortFlag); +int imgif_emmc_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoP); +int imgif_emmc_get_flash_info(imgif_flash_info_t *flashInfoP); + +#endif /* CMS_IMGIF_EMMC_H */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_nand.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_nand.c new file mode 100755 index 00000000000..27c44eead71 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_nand.c @@ -0,0 +1,1244 @@ +/***************************************************************************** + * <:copyright-BRCM:2015:DUAL/GPL:standard + * + * Copyright (c) 2015 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ****************************************************************************/ + +/***************************************************************************** +* Description: +* +* The BCM CPE software Image Incremental Flashing (imageIf) library +* implementation. This library runs on top of bcm_flashutil. It uses +* the incremental flashing mechanism to avoid holding the entire image +* in RAM, thus reduces RAM usage. +* This library is expected to be platform-independent. The underlying +* bcm_flashutil library handles the platform-specific operations. +* Notes about the library: +* - It supports FLASH format image, with a Whole Flash Image WFI_TAG +* (length TOKEN_LEN) trailer. It supports NAND flash. +* - It assumes CFEROM stays on erase block #0 only. +* - It does not handle BROADCOM format image or NOR flash. +* - It does not handle the configuration file upgrade, and messages +* related to the configuration file validation. +* +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ + +#include +#include +#include +#include + +#include "bcmTag.h" +#include "genutil_crc.h" +#include "board.h" +#include "bcm_flashutil.h" +#include "bcm_flashutil_private.h" +#include "bcm_flashutil_nand.h" +#include "bcm_imgif.h" +#include "bcm_imgif_nand.h" + +#include "flash_api.h" + +/* ---- Private Constants and Types --------------------------------------- */ + +/* #define CC_IMGIF_DEBUG 1 */ + +#define MTD_NAME_IMAGE "image" +#define MTD_NAME_IMAGE_UPDATE "image_update" +#define CFERAM_NAME_LEN 20 +#define CFERAM_SIZE (9 * eraseSize) +#define IMG_TRAILER_LEN TOKEN_LEN +#define BCM_BCMFS_TAG_OFFSET 0x100 +#define FLASH_ERASE_ITERATIONS 3 + +#define getCtx() (&imgifCtx) +#define getCtxByHandle(h) ((imgif_ctx_t*)h) +#define copyDataToBucket(ctxP, usrP, copyLen) \ +{ \ + memcpy(ctxP->currP, usrP, copyLen); \ + ctxP->currP += copyLen; \ + ctxP->curSize += copyLen; \ + ctxP->usrBytes += copyLen; \ +} +#define getProcessedDataLen(ctxP) ((ctxP->curSize > ctxP->eraseSize)? \ + ctxP->eraseSize : ctxP->curSize); +#define getFlashOffsetForCferam(s) (9 * s) + +#if defined(CC_IMGIF_DEBUG) +#define imgif_debug(fmt, arg...) \ + printf("%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#define DUMPIMGIFCTX(cxtP) dumpImgifCtx(ctxP) +#define DUMPWFITAG(wtP) dumpWfiTag(wtP) +#else +#define imgif_debug(fmt, arg...) +#define DUMPIMGIFCTX(cxtP) +#define DUMPWFITAG(wtP) +#endif + +#define imgif_error(fmt, arg...) \ + printf("ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + + +/* IMGIF NAND context. */ +typedef struct +{ + /* + * FLASH info: + * + * flashInfo - NOR or NAND. + * flashSize - total flash size. + * nvramDataP - nvram data from flash, used for cferom flashing. + * eraseSize - flash erase size. + * secureBoot - boot information. + * btrmEnable - boot information. + */ + UINT32 flashInfo; + UINT32 flashSize; + NVRAM_DATA *nvramDataP; + UINT32 eraseSize; + UBOOL8 secureBoot; + UBOOL8 btrmEnable; + + /* MTD info for MTD_NAME_IMAGE_UPDATE. */ + mtd_info_t *mtdP; + int mtdFd; + + /* + * Software image info: + * + * fmtParserCb - image format parser callback function. + * calCrc32Cb - application-specific CRC algorithm, OMCI uses I.363.5. + * imgFormat - only flash-format image is supported. + * cferamFname - cferam name embedded in file. + * imgInfoBi - built-in image information (size, crc). + * imgInfoExt - application-provided image information. + * imgSize - calculated image size. + * crcBody - image content crc (excluding WFI_TAG). + * crcAll - whole image crc. + * wfiFlags - whole flash image flags, refer WFI_TAG. + * imageType - image type, either JFFS2 (which includes UBI split) or + pureUBI. + * cferomFound - image includes cferom (optional). + * cferamSize - cferam size, always = eraseSize. + * cferomSize - cferom size, always = eraseSize. + * cferamDirOffset - cferam dirp offset. + * cferamP - saved CFERAM sequence number block local copy before flashing. + * cferamP2 - saved second CFERAM sequence number block (if needed, pureUBI for example) local copy before flashing. + * cferomP - saved CFEROM block local copy before flashing. + */ + IMG_FORMAT_PARSER_CB fmtParserCb; + CAL_CRC32_CB calCrc32Cb; + UINT32 imgFormat; + imgif_img_info_t imgInfoBi; + imgif_img_info_t imgInfoExt; + UINT32 imgSize; + UINT32 crcBody; + UINT32 crcAll; + UINT32 wfiFlags; + UINT32 imageType; + UBOOL8 cferomFound; + UINT32 cferamSize; + UINT32 cferomSize; + UINT8 *cferamP; + UINT8 *cferamP2; + UINT8 *cferomP; + + /* + * Run time upgrade info: + * + * upgradeState - refer imgif_state_e. + * usrBlks - processed blocks from user, not necessarily = flashedBlks. + * usrBytes - copied bytes from user. + * flashedBlks - programmed flash blocks. + * flashedBytes - programmed flash bytes. + * procBytes - processed user bytes. + * startP - bucket starting pointer. + * endP - bucket end pointer. + * currP - current image segment end pointer. + * curSize - current image segment size. + * flashBlkCferam - cferam end address on flash. + * flashBlkAddr - current flash programming addr. + * cferamSeqNum - cferam sequence number. + * cferamSeqBlksFound - the number of discovered cferam blocks with a + sequence number. + * writingUbifs - ubifs split marker. + * lastB - last block processing. + */ + imgif_state_e upgradeState; + UINT32 bucketSize; + UINT32 usrBlks; + UINT32 usrBytes; + UINT32 flashedBlks; + UINT32 flashedBytes; + UINT32 procBytes; + UINT32 curSize; + UINT8 *startP; + UINT8 *currP; + UINT8 *endP; + UINT32 flashBlkCferam; + UINT32 flashBlkAddr; + int cferamSeqNum; + int cferamSeqBlksFound; + UBOOL8 writingUbifs; + UBOOL8 lastB; +} imgif_ctx_t; + +/* ---- Private Function Prototypes --------------------------------------- */ + +static imgif_ret_e imgif_ctx_init(imgif_ctx_t *ctxP); +static imgif_ret_e imgif_ctx_clean(imgif_ctx_t *ctxP); +static imgif_ret_e checkCferom(imgif_ctx_t *ctxP); +static imgif_ret_e procData(imgif_ctx_t *ctxP); +static imgif_ret_e procSearchCferam(imgif_ctx_t *ctxP); +static imgif_ret_e procFlashFs(imgif_ctx_t *ctxP); +static imgif_ret_e procUpdateAndFlashCferam(imgif_ctx_t *ctxP); +static imgif_ret_e procFlashCferom(imgif_ctx_t *ctxP); +static void postProcMoveData(imgif_ctx_t *ctxP); +static UINT32 getFlashType(void); +static int initSeqNum(void); +static UINT32 getFlashImgCrc(UINT8 *crcP); +static void eraseCferamBlock(imgif_ctx_t *ctxP); +static void eraseRemainingBlocks(imgif_ctx_t *ctxP); +static int flashNormalBlock(imgif_ctx_t *ctxP, UINT8 *bufP, UINT32 writeLen); +static UBOOL8 hasEnoughDataToProc(imgif_ctx_t *ctxP); +void dumpImgifCtx(imgif_ctx_t *ctxP); +void dumpWfiTag(WFI_TAG *wtP); + +/* ---- Public Variables -------------------------------------------------- */ + +/* ---- Private Variables ------------------------------------------------- */ + +static imgif_ctx_t imgifCtx; + + +/* ---- Functions --------------------------------------------------------- */ +/***************************************************************************** +* FUNCTION: imgif_nand_open +* PURPOSE: Initialize IMGIF context. +* PARAMETERS: +* fmtParserCb (IN) Image parser callback function. + calCrc32Cb (IN) Application-specific CRC algorithm callback function. +* RETURNS: +* Pointer to the IMGIF context - successful operation. +* NULL - failed operation, for example, another software upgrade already +* in progress. +* NOTES: +* None. +*****************************************************************************/ +IMGIF_HANDLE imgif_nand_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb) +{ + imgif_ctx_t *ctxP; + mtd_info_t *mtdP; + int mtdFd; + imgif_ret_e ret; + + imgif_debug("Enter."); + + ctxP = getCtx(); + DUMPIMGIFCTX(ctxP); + + if (ctxP->startP != NULL) + { + imgif_error("Another upgrade is in progress."); + return (IMGIF_HANDLE)NULL; + } + + memset(ctxP, 0x0, sizeof(imgif_ctx_t)); + ctxP->flashInfo = getFlashType(); + + if ((ctxP->flashInfo & FLASH_INFO_FLAG_NAND) == 0) + { + imgif_error("This library does not support NOR flash."); + return (IMGIF_HANDLE)NULL; + } + + mtdP = get_mtd_device_handle(MTD_NAME_IMAGE, &mtdFd, 0); + if (mtdP == 0) + { + imgif_error("get_mtd_device_handle(%s) failed", MTD_NAME_IMAGE); + return (IMGIF_HANDLE)NULL; + } + else + { + put_mtd_device(mtdP, mtdFd, -1); + } + + mtdP = get_mtd_device_handle(MTD_NAME_IMAGE_UPDATE, &mtdFd, 0); + if (mtdP == NULL) + { + imgif_error("get_mtd_device_handle(%s) failed", MTD_NAME_IMAGE_UPDATE); + return (IMGIF_HANDLE)NULL; + } + else + { + ctxP->mtdP = mtdP; + ctxP->mtdFd = mtdFd; + ctxP->eraseSize = mtdP->erasesize; + ctxP->flashSize = mtdP->size; + } + + ret = imgif_ctx_init(ctxP); + if (ret != IMGIF_PROC_OK) + { + imgif_error("imgif_ctx_init() failed."); + return (IMGIF_HANDLE)NULL; + } + + ctxP->upgradeState = IMGIF_UPGRADE_SEARCH; + + ctxP->fmtParserCb = fmtParserCb; + ctxP->calCrc32Cb = calCrc32Cb; + if (ctxP->calCrc32Cb != NULL) + { + ctxP->calCrc32Cb(0, &ctxP->crcAll, NULL, 0); + } + + DUMPIMGIFCTX(ctxP); + + return (IMGIF_HANDLE)ctxP; +} + +/***************************************************************************** +* FUNCTION: imgif_nand_set_image_info +* PURPOSE: Set image info obtained externally. +* PARAMETERS: + h (IN) - IMGIF context pointer. + imgInfoExtP (OUT) - image info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. However, it is typically +* invoked at the end of the upgrade, when user has received the whole +* image, and has obtained the image integrity information. +*****************************************************************************/ +int imgif_nand_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoExtP) +{ + imgif_ctx_t *ctxP; + + imgif_debug("Enter, h=%p, info=%p.", h, imgInfoExtP); + + ctxP = getCtxByHandle(h); + if ((ctxP != NULL) && (imgInfoExtP != NULL)) + { + ctxP->imgInfoExt.bitmask = imgInfoExtP->bitmask; + ctxP->imgInfoExt.size = imgInfoExtP->size; + ctxP->imgInfoExt.crc = imgInfoExtP->crc; + return 0; + } + + return -1; +} + +/***************************************************************************** +* FUNCTION: imgif_nand_get_flash_info +* PURPOSE: Obtain flash info. +* PARAMETERS: + h (IN) - IMGIF context pointer. + flashInfoP (OUT) - flash info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. +*****************************************************************************/ +int imgif_nand_get_flash_info(imgif_flash_info_t *flashInfoP) +{ + mtd_info_t *mtdP; + int mtdFd; + + imgif_debug("Enter, info=%p.", flashInfoP); + + flashInfoP->flashType = getFlashType(); + + mtdP = get_mtd_device_handle(MTD_NAME_IMAGE_UPDATE, &mtdFd, 0); + if (mtdP == NULL) + { + imgif_error("get_mtd_device_handle(%s) failed", MTD_NAME_IMAGE_UPDATE); + return -1; + } + else + { + flashInfoP->eraseSize = mtdP->erasesize; + flashInfoP->flashSize = mtdP->size; + } + + return 0; +} + +/***************************************************************************** +* FUNCTION: imgif_nand_write +* PURPOSE: Write image block to IMGIF. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* dataP (IN) - image block data pointer. +* len (IN) - image block size. +* RETURNS: +* >=0 - number of bytes written. +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +int imgif_nand_write(IMGIF_HANDLE h, UINT8 *dataP, int len) +{ + imgif_ctx_t *ctxP; + int remainLen = len; + int copyLen = 0; + int writeBytes = 0; + UINT8 *usrP = dataP; + imgif_ret_e ret; + + if ((h == NULL) || (dataP == NULL)) + { + imgif_error("Invalid params"); + return -1; + } + + ctxP = getCtxByHandle(h); + + imgif_debug("Enter, dataP=%p, len=%d.", dataP, len); + DUMPIMGIFCTX(ctxP); + + if (ctxP->calCrc32Cb != NULL) + { + ctxP->calCrc32Cb(1, &ctxP->crcAll, dataP, len); + } + + do + { + copyLen = ((ctxP->currP + remainLen) > ctxP->endP) ? + (ctxP->endP - ctxP->currP) : remainLen; + imgif_debug("Copy from user, usrP=%p, copyLen=%d.", usrP, copyLen); + if (copyLen == 0) + { + break; + } + + copyDataToBucket(ctxP, usrP, copyLen); + + usrP += copyLen; + remainLen -= copyLen; + writeBytes += copyLen; + if (hasEnoughDataToProc(ctxP)) + { + ret = procData(ctxP); + if (ret == IMGIF_PROC_ERR) + { + /* Abort. */ + writeBytes = -1; + break; + } + ctxP->usrBlks++; + } + + DUMPIMGIFCTX(ctxP); + + } while (remainLen > 0); + + if (writeBytes != len) + { + imgif_error("imgif_write() len=%d, written=%d", len, writeBytes); + } + + DUMPIMGIFCTX(ctxP); + + imgif_debug("Exit, len=%d, written=%d", len, writeBytes); + + return writeBytes; +} + +/***************************************************************************** +* FUNCTION: imgif_nand_close +* PURPOSE: Close IMGIF context. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* abortFlag (IN) - TRUE: user aborts the operation. +* RETURNS: +* 0 - successful operation. +* -1 - failed operation. +* NOTES: +* User may stop an upgrade at any time, when there is an operator, +* command, protocol failure, or unmatched image size and/or CRC values +* between IMGIF and user. +*****************************************************************************/ +int imgif_nand_close(IMGIF_HANDLE h, UBOOL8 abortFlag) +{ + imgif_ctx_t *ctxP; + imgif_ret_e imgifRet; + UINT8 *tagP; + int blkSize; + WFI_TAG wt; + int ret = -1; + + if (h == NULL) + { + imgif_error("Invalid params"); + return -1; + } + + ctxP = getCtxByHandle(h); + imgif_debug("Enter, h=%p, flag=%d.", h, abortFlag); + + if (abortFlag == TRUE) + { + ret = 0; + goto imgif_close_exit; + } + + if (ctxP->curSize < IMG_TRAILER_LEN) + { + imgif_error("Unexpected state, curSize=%d", ctxP->curSize); + goto imgif_close_exit; + } + + tagP = ctxP->currP - IMG_TRAILER_LEN; + memcpy(&wt, tagP, sizeof(wt)); + + DUMPWFITAG(&wt); + + DUMPIMGIFCTX(ctxP); + + blkSize = ctxP->eraseSize / 1024; + + if (validateWfiTag(&wt, blkSize, ctxP->btrmEnable) < 0) + { + imgif_error("Unexpected WFI tag content"); + goto imgif_close_exit; + } + + ctxP->imgInfoBi.bitmask = IMG_INFO_BITMASK_CRC; + ctxP->imgInfoBi.crc = getFlashImgCrc(tagP); + ctxP->wfiFlags = wt.wfiFlags; + + /* Image integrity check. */ + + ctxP->imgSize = ctxP->usrBytes; + + if (ctxP->calCrc32Cb != NULL) + { + ctxP->calCrc32Cb(2, &ctxP->crcAll, NULL, 0); + } + + if ((ctxP->imgInfoExt.bitmask & IMG_INFO_BITMASK_CRC) && + (ctxP->imgInfoExt.crc != ctxP->crcAll)) + { + imgif_error("Unmatched file CRC values, ext=0x%08x, cal=0x%08x", + ctxP->imgInfoExt.crc, ctxP->crcAll); + goto imgif_close_exit; + } + + if ((ctxP->imgInfoBi.bitmask & IMG_INFO_BITMASK_CRC) && + (ctxP->imgInfoBi.crc != ctxP->crcBody)) + { + imgif_error("Unmatched file CRC values, bi=0x%08x, cal=0x%08x", + ctxP->imgInfoBi.crc, ctxP->crcBody); + goto imgif_close_exit; + } + + if ((ctxP->imgInfoExt.bitmask & IMG_INFO_BITMASK_SIZE) && + (ctxP->imgInfoExt.size != ctxP->imgSize)) + { + imgif_error("Unmatched file size values, ext=0x%08x, cal=0x%08x", + ctxP->imgInfoExt.size, ctxP->imgSize); + goto imgif_close_exit; + } + + ctxP->upgradeState = IMGIF_UPGRADE_FS_FINAL; + ctxP->lastB = TRUE; + + /* Adjust ctx, not to flash IMG_TRAILER_LEN. */ + ctxP->currP -= IMG_TRAILER_LEN; + ctxP->curSize -= IMG_TRAILER_LEN; + + /* Flash remaining data. */ + if (ctxP->curSize > 0) + { + imgifRet = procData(ctxP); + if (imgifRet == IMGIF_PROC_OK) + { + postProcMoveData(ctxP); + } + else if (imgifRet == IMGIF_PROC_ERR) + { + imgif_error("procData() failed, ret=%d.", imgifRet); + goto imgif_close_exit; + } + } + + /* + * Erase remaining blocks. This follows existing full-image upgrade + * implementation, however it may not be required. + */ + eraseRemainingBlocks(ctxP); + + /* Flash cferam. */ + imgifRet = procUpdateAndFlashCferam(ctxP); + if (imgifRet == IMGIF_PROC_ERR) + { + imgif_error("procUpdateAndFlashCferam() failed, ret=%d.", imgifRet); + goto imgif_close_exit; + } + + /* Flash cferom, must be the last one. */ + if (ctxP->cferomFound == TRUE) + { + if (handleCferom(ctxP->mtdP, (char*)ctxP->cferomP, ctxP->cferomSize, ctxP->wfiFlags, + ctxP->nvramDataP) < 0) + { + imgif_error("handleCferom() failed."); + goto imgif_close_exit; + } + + imgifRet = procFlashCferom(ctxP); + if (imgifRet == IMGIF_PROC_ERR) + { + imgif_error("procFlashCferom() failed, ret=%d.", imgifRet); + goto imgif_close_exit; + } + } + + ret = 0; + +imgif_close_exit: + DUMPIMGIFCTX(ctxP); + imgif_ctx_clean(ctxP); + return ret; +} + +/* ---- Private Functions ------------------------------------------------- */ + +static imgif_ret_e imgif_ctx_init(imgif_ctx_t *ctxP) +{ + int seq; + + ctxP->bucketSize = ctxP->eraseSize + IMG_TRAILER_LEN; + ctxP->startP = malloc(ctxP->bucketSize); + if (ctxP->startP == NULL) + { + imgif_error("malloc(%d) failed.", ctxP->bucketSize); + goto init_exit; + } + + ctxP->crcBody = CRC_INITIAL_VALUE; + ctxP->crcAll = CRC_INITIAL_VALUE; + + ctxP->currP = ctxP->startP; + ctxP->endP = ctxP->startP + ctxP->bucketSize; + + ctxP->nvramDataP = malloc(sizeof(NVRAM_DATA)); + if (ctxP->nvramDataP == NULL) + { + imgif_error("malloc(%d) failed.", (int)sizeof(NVRAM_DATA)); + goto init_exit; + } + + if (readNvramData(ctxP->nvramDataP) <= 0) + { + imgif_error("readNvramData() failed"); + goto init_exit; + } + + seq = initSeqNum(); + if (seq < 0) + { + imgif_error("initSeqNum() failed, seq=%d", seq); + goto init_exit; + } + + ctxP->cferamSeqNum = seq; + ctxP->upgradeState = IMGIF_UPGRADE_IDLE; + + /* Information only. */ + ctxP->secureBoot = otp_is_boot_secure(); + ctxP->btrmEnable = otp_is_btrm_boot(); + + return IMGIF_PROC_OK; + +init_exit: + imgif_ctx_clean(ctxP); + return IMGIF_PROC_ERR; +} + +static imgif_ret_e imgif_ctx_clean(imgif_ctx_t *ctxP) +{ + if (ctxP->startP != NULL) + { + free(ctxP->startP); + ctxP->startP = NULL; + ctxP->endP = NULL; + ctxP->currP = NULL; + } + + if (ctxP->nvramDataP != NULL) + { + free(ctxP->nvramDataP); + ctxP->nvramDataP = NULL; + } + + if (ctxP->mtdP != NULL) + { + put_mtd_device(ctxP->mtdP, ctxP->mtdFd, -1); + ctxP->mtdP = NULL; + ctxP->mtdFd = 0; + } + + if (ctxP->cferomP != NULL) + free(ctxP->cferomP); + + if (ctxP->cferamP != NULL) + free(ctxP->cferamP); + + if (ctxP->cferamP2 != NULL) + free(ctxP->cferamP2); + + ctxP->cferamSeqNum = -1; + + return IMGIF_PROC_OK; +} + +void dumpImgifCtx(imgif_ctx_t *ctxP) +{ + printf("--------------------------------------------------------------\n"); + printf("Software image info:\n"); + printf("\tformat=%d\n", ctxP->imgFormat); + + printf("\timgInfo(ext): bitmask=%x, crc=0x%08x, size=%d\n", + ctxP->imgInfoExt.bitmask, ctxP->imgInfoExt.crc, ctxP->imgInfoExt.size); + printf("\timgInfo(bi): bitmask=%x, crc=0x%08x, size=%d\n", + ctxP->imgInfoBi.bitmask, ctxP->imgInfoBi.crc, ctxP->imgInfoBi.size); + printf("\timgInfo(cal): crcBody=0x%08x, crcAll=0x%08x, size=%d\n", + ctxP->crcBody, ctxP->crcAll, ctxP->imgSize); + + printf("\tcferam: saved=%p, seq=%d\n", + ctxP->cferamP, ctxP->cferamSeqNum); + printf("\tcferam2: saved=%p, seq=%d\n", + ctxP->cferamP2, ctxP->cferamSeqNum); + printf("\tcferom: found=%d, saved=%p\n", + ctxP->cferomFound, ctxP->cferomP); + printf("Run time upgrade info:\n"); + printf("\tstate=%d, lastB=%d\n", ctxP->upgradeState, ctxP->lastB); + printf("\tbucketSize=%d, startP=%p, endP=%p, currP=%p,\n" + "\teraseSize=0x%x, curSize=%d\n", + ctxP->bucketSize, ctxP->startP, ctxP->endP, ctxP->currP, + ctxP->eraseSize, ctxP->curSize); + printf("\tuser: blocks=%d, bytes=%d\n", + ctxP->usrBlks, ctxP->usrBytes); + printf("\tflash: addr=%u, cferam=%u, blocks=%d, bytes=%d\n", + ctxP->flashBlkAddr, ctxP->flashBlkCferam, + ctxP->flashedBlks, ctxP->flashedBytes); + printf("--------------------------------------------------------------\n"); +} + +void dumpWfiTag(WFI_TAG *wtP) +{ + printf("WFI tag:\n"); + printf("\t CRC: 0x%08x\n", wtP->wfiCrc); + printf("\t Version: 0x%08x\n", wtP->wfiVersion); + printf("\t Chip ID: 0x%08x\n", wtP->wfiChipId); + printf("\t Flash Type: 0x%08x\n", wtP->wfiFlashType); + printf("\t Flags: 0x%08x\n", wtP->wfiFlags); +} + +static int initSeqNum(void) +{ + int seq = -1; + + /* Get sequence number of booted partition. */ + seq = getSequenceNumber(getBootPartition()); + imgif_debug("Get seq# %d.", seq); + + if (seq == -1) + { + return seq; + } + + return (seq); +} + +static UBOOL8 hasEnoughDataToProc(imgif_ctx_t *ctxP) +{ + UBOOL8 enough = FALSE; + + if (ctxP->lastB == TRUE) + { + enough = TRUE; + } + else + { + if ((ctxP->curSize >= IMG_TRAILER_LEN) && + (ctxP->curSize - IMG_TRAILER_LEN) >= ctxP->eraseSize) + { + enough = TRUE; + } + } + + return enough; +} + +static UINT32 getFlashType(void) +{ + unsigned int flags = 0; + UINT32 flashType = 0; + int ret; + + ret = getFlashInfo(&flags); + if (ret >= 0) /* OK */ + { + if (flags & FLASH_INFO_FLAG_NAND) + { + flashType = FLASH_INFO_FLAG_NAND; + } + } + else + { + imgif_error("getFlashInfo() failed, ret=%d.", ret); + } + + return flashType; +} + +/* Get CRC value from WFI tag. */ +static UINT32 getFlashImgCrc(UINT8 *crcP) +{ + UINT32 imageCrc; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + imageCrc = crcP[0] | (crcP[1] << 8) | (crcP[2] << 16) | (crcP[3] << 24); +#else + imageCrc = (crcP[0] << 24) | (crcP[1] << 16) | (crcP[2] << 8) | crcP[3]; +#endif + return imageCrc; +} + +static void eraseCferamBlock(imgif_ctx_t *ctxP) +{ + UINT32 blkAddr; + + for (blkAddr = 0; blkAddr < ctxP->flashBlkCferam; + blkAddr += ctxP->eraseSize) + { + imgif_debug("nandEraseBlk() blkAddr=0x%x, " + "erasesize=%u, blkCferam=0x%x\n", + blkAddr, ctxP->eraseSize, ctxP->flashBlkCferam); + nandEraseBlk(ctxP->mtdP, blkAddr, ctxP->mtdFd); + } +} + +static int flashNormalBlock(imgif_ctx_t *ctxP, UINT8 *bufP, UINT32 writeLen) +{ + UINT8 *tagP; + UINT8 iterations = 0; + UBOOL8 eraseOK = FALSE; + + if (writeLen == 0) + { + imgif_error("writeLen = 0"); + return -1; + } + + printf("."); + fflush(stdout); + + for (; (ctxP->flashBlkAddr < ctxP->flashSize); + ctxP->flashBlkAddr += ctxP->eraseSize, iterations = 0) + { + do + { + if (nandEraseBlk(ctxP->mtdP, ctxP->flashBlkAddr, ctxP->mtdFd) == 0) + { + eraseOK = TRUE; + break; + } + else + { + imgif_error("nandEraseBlk() failed, blkAddr=0x%x, iteration=%d", + ctxP->flashBlkAddr, iterations); + } + + } while (++iterations < FLASH_ERASE_ITERATIONS); + + if (eraseOK == TRUE) + { + break; + } + } + + if (eraseOK == FALSE) + { + imgif_error("nandEraseBlk() failed, blkAddr=0x%x, flashsize=0x%x", + ctxP->flashBlkAddr, ctxP->flashSize); + return -1; + } + + imgif_debug("nandWriteBlk(), blkAddr=0x%x, erasesize=%u, " + "bufP=%p, writeLen=%u", + ctxP->flashBlkAddr, ctxP->eraseSize, bufP, writeLen); + + if (nandWriteBlk(ctxP->mtdP, ctxP->flashBlkAddr, writeLen, bufP, + ctxP->mtdFd, !ctxP->writingUbifs) != 0) + { + imgif_error("Error writing block 0x%8x, len%d, skipping\n", + ctxP->flashBlkAddr, writeLen); + return -1; + } + else + { + if (writeLen >= ctxP->eraseSize) + { + tagP = bufP + writeLen - BCM_BCMFS_TAG_OFFSET; + if (!strncmp(BCM_BCMFS_TAG, (char*)tagP, strlen(BCM_BCMFS_TAG))) + { + if (!strncmp(BCM_BCMFS_TYPE_UBIFS, + (char*)tagP + strlen(BCM_BCMFS_TAG), + strlen(BCM_BCMFS_TYPE_UBIFS))) + { + ctxP->writingUbifs = TRUE; + printf("U"); + fflush(stdout); + } + } + } + else + { + /* Must be the last write. */ + imgif_debug("Writing last block 0x%8x, len%d", + ctxP->flashBlkAddr, writeLen); + } + } + + return 0; +} + +static void postProcMoveData(imgif_ctx_t *ctxP) +{ + UINT32 moveBufLen; + + if (ctxP->curSize > ctxP->eraseSize) + { + moveBufLen = ctxP->curSize - ctxP->eraseSize; + memcpy(ctxP->startP, (ctxP->currP - moveBufLen), + moveBufLen); + ctxP->currP = ctxP->startP + moveBufLen; + ctxP->curSize -= ctxP->eraseSize; + } + else + { + ctxP->currP = ctxP->startP; + ctxP->curSize = 0; + } +} + +static imgif_ret_e checkCferom(imgif_ctx_t *ctxP) +{ + UBOOL8 cferomExist = FALSE; + + cferomExist = nand_image_type(ctxP->startP) ? + FALSE : TRUE; + + if (cferomExist == FALSE) + { + return IMGIF_PROC_NOT_FOUND; + } + + ctxP->cferomP = realloc(ctxP->cferomP, ctxP->cferomSize + ctxP->eraseSize); + if (ctxP->cferomP == NULL) + { + imgif_error("malloc(%d) failed.", ctxP->eraseSize); + return IMGIF_PROC_ERR; + } + + memcpy(ctxP->cferomP + ctxP->cferomSize, ctxP->startP, ctxP->eraseSize); + ctxP->cferomFound = TRUE; + ctxP->cferomSize += ctxP->eraseSize; + return IMGIF_PROC_FOUND; +} + +static imgif_ret_e parseImgHdr(imgif_ctx_t *ctxP) +{ + CmsImageFormat imgFormat = CMS_IMAGE_FORMAT_INVALID; + + if (ctxP->fmtParserCb != NULL) + { + imgFormat = ctxP->fmtParserCb(ctxP->startP, + ctxP->curSize); + } + + /* FORMAT_INVALID is also used for unknown. */ + if (imgFormat != CMS_IMAGE_FORMAT_INVALID) + { + if (imgFormat != CMS_IMAGE_FORMAT_FLASH) + { + imgif_error("Image format %d not supported.\n", + imgFormat); + return IMGIF_PROC_ERR; + } + else + { + ctxP->imgFormat = imgFormat; + } + } + + return IMGIF_PROC_OK; +} + +static imgif_ret_e procData(imgif_ctx_t *ctxP) +{ + imgif_state_e curState, newState; + imgif_ret_e ret = IMGIF_PROC_OK; + UBOOL8 moveOn = FALSE; + UINT32 procBytes = getProcessedDataLen(ctxP); + UBOOL8 flashFs = FALSE; + UINT32 crc = genUtl_getCrc32(ctxP->startP, procBytes, ctxP->crcBody); + curState = ctxP->upgradeState; + newState = curState; + + if (!ctxP->imageType) + { + if ((ctxP->imageType = nand_image_type(ctxP->startP))) + { // image type is not determined until after CFEROM block + /* We're past the CFEROM, adjust the flash address accordingly. */ + if (ctxP->cferomP) + { // check to see if CFEROM size matches expected size + int mtd_fd; + mtd_info_t *mtd = get_mtd_device_handle("nvram", &mtd_fd, 0); + + if( mtd > 0 ) + { + if (mtd->size != ctxP->cferomSize) + { + imgif_error("ERROR!!! Image CFEROM size of 0x%x is not equal to the nvram partition size of 0x%x", ctxP->cferomSize, mtd->size); + put_mtd_device(mtd, mtd_fd, -1); + return IMGIF_PROC_ERR; + } + } + else + { + imgif_error("Failed to get nvram mtd device!!!"); + return IMGIF_PROC_ERR; + } + } + + ctxP->flashBlkCferam = getFlashOffsetForCferam(ctxP->eraseSize); + ctxP->flashBlkAddr = ctxP->flashBlkCferam; + eraseCferamBlock(ctxP); // this must go here after we have determined imagetype so that ctxP parameters are populated properly, CFEROM won't have been written as it was saved, and CFERAM blocks will not yet have been written + } + } + + if (curState == IMGIF_UPGRADE_SEARCH) + { + /* Parse image header. */ + if (!ctxP->imageType) + { + if (parseImgHdr(ctxP) != IMGIF_PROC_OK) + { + return IMGIF_PROC_ERR; + } + + /* If exists, cferom is in the first block(s). */ + ret = checkCferom(ctxP); + if (ret == IMGIF_PROC_FOUND) + { + /* Skip the cferom. */ + moveOn = TRUE; + } + } + else + { + ret = procSearchCferam(ctxP); + + if (ret == IMGIF_PROC_FOUND) + { // CFERAM block with sequence number found + /* Skip the cferam. */ + moveOn = TRUE; + ctxP->writingUbifs = FALSE; + } + else if (ret == IMGIF_PROC_NOT_FOUND) + { + flashFs = TRUE; + } + + if ( (ctxP->cferamP) && ((ctxP->imageType == JFFS2_IMAGE) || (ctxP->cferamP2)) ) + { // this allows for finalization of image upgrade which lets state machine know that CFERAM sequence number blocks have been found + newState = IMGIF_UPGRADE_FS; + } + } + } + else if ((curState == IMGIF_UPGRADE_FS) || + (curState == IMGIF_UPGRADE_FS_FINAL)) + { + flashFs = TRUE; + } + + if (flashFs == TRUE) + { + ret = procFlashFs(ctxP); + if (ret == IMGIF_PROC_OK) + { + moveOn = TRUE; + ctxP->flashBlkAddr += ctxP->eraseSize; + } + else + { + return IMGIF_PROC_ERR; + } + } + + if (moveOn == TRUE) + { + ctxP->procBytes += procBytes; + ctxP->crcBody = crc; + postProcMoveData(ctxP); + } + ctxP->upgradeState = newState; + + return IMGIF_PROC_OK; +} + +static imgif_ret_e procSearchCferam(imgif_ctx_t *ctxP) +{ + unsigned char *cferamP; + + /* + * Check and process cferam number in cferam block which contains + * the cferam number. + */ + cferamP = nandUpdateSeqNum(ctxP->startP, ctxP->eraseSize, ctxP->eraseSize, + ctxP->cferamSeqNum, &ctxP->cferamSeqBlksFound); + if (cferamP == NULL) + { + imgif_debug("Not a block containing cferam"); + } + else + { // CFERAM block with sequence number found + imgif_debug("Found a block containing cferam, startP=%p, cferamP=%p", + ctxP->startP, cferamP); + + /* Found. */ + ctxP->cferamSize = ctxP->eraseSize; + + if (ctxP->cferamP == NULL) + { + if ((ctxP->cferamP = malloc(ctxP->cferamSize)) == NULL) + { + imgif_error("malloc(%d) failed.", ctxP->cferamSize); + return(IMGIF_PROC_ERR); + } + + memcpy(ctxP->cferamP, cferamP, ctxP->cferamSize); + return(IMGIF_PROC_FOUND); + } + + if ((ctxP->cferamP2 = malloc(ctxP->cferamSize)) == NULL) + { + imgif_error("malloc(%d) failed.", ctxP->cferamSize); + return(IMGIF_PROC_ERR); + } + + memcpy(ctxP->cferamP2, cferamP, ctxP->cferamSize); + return(IMGIF_PROC_FOUND); + } + + return(IMGIF_PROC_NOT_FOUND); +} + +static imgif_ret_e procFlashFs(imgif_ctx_t *ctxP) +{ + int writeLen; + imgif_ret_e ret = IMGIF_PROC_ERR; + + writeLen = (ctxP->curSize >= ctxP->eraseSize) ? + (int)ctxP->eraseSize : (int)ctxP->curSize; + + if (flashNormalBlock(ctxP, ctxP->startP, writeLen) == 0) + { + ctxP->flashedBytes += writeLen; + ctxP->flashedBlks++; + ret = IMGIF_PROC_OK; + } + + return ret; +} + +static imgif_ret_e procUpdateAndFlashCferam(imgif_ctx_t *ctxP) +{ + int ret; + + if (ctxP->cferamP == NULL) + { + imgif_error("Invalid cferam pointer."); + return IMGIF_PROC_ERR; + } + + ret = flashCferam(ctxP->mtdP, ctxP->mtdFd, (int)ctxP->flashBlkCferam, + ctxP->cferamP, ctxP->cferamP2); + if (ret < 0) + { + imgif_error("flashCferam(%p, 0x%x, %u, %p) failed.", + ctxP->mtdP, ctxP->mtdFd, ctxP->flashBlkCferam, ctxP->cferamP); + eraseCferamBlock(ctxP); + return IMGIF_PROC_ERR; + } + + ctxP->flashedBytes += ctxP->cferamSize; + ctxP->flashedBlks++; + + return IMGIF_PROC_OK; +} + +static imgif_ret_e procFlashCferom(imgif_ctx_t *ctxP) +{ + int ret; + + ret = flashCferom(ctxP->cferomP, ctxP->cferomSize); + if (ret < 0) + { + imgif_error("flashCferom(%p, 0x%x, %d) failed.", + ctxP->cferomP, ctxP->wfiFlags, ctxP->cferomSize); + } + + ctxP->flashedBytes += ctxP->cferomSize; + ctxP->flashedBlks += ctxP->cferomSize/ctxP->eraseSize; + + return IMGIF_PROC_OK; +} + +static void eraseRemainingBlocks(imgif_ctx_t *ctxP) +{ + UINT32 blkAddr; + + for (blkAddr = ctxP->flashBlkAddr; blkAddr < (UINT32)ctxP->mtdP->size; + blkAddr += ctxP->eraseSize) + { + printf("."); + fflush(stdout); + imgif_debug("nandEraseBlk() blkAddr=0x%x, erasesize=%u\n", + blkAddr, ctxP->eraseSize); + nandEraseBlk(ctxP->mtdP, blkAddr, ctxP->mtdFd); + } +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_nand.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_nand.h new file mode 100644 index 00000000000..a52d3ae5d19 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_nand.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * + * Copyright (c) 2015 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2015:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * + ****************************************************************************/ + +#ifndef BCM_IMGIF_NAND_H +#define BCM_IMGIF_NAND_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include "bcm_imgif.h" + +/* ---- Constants and Types ----------------------------------------------- */ +/* ---- Variable Externs -------------------------------------------------- */ +/* ---- Function Prototypes ----------------------------------------------- */ + +IMGIF_HANDLE imgif_nand_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb); +int imgif_nand_write(IMGIF_HANDLE h, UINT8 *dataP, int len); +int imgif_nand_close(IMGIF_HANDLE h, UBOOL8 abortFlag); +int imgif_nand_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoP); +int imgif_nand_get_flash_info(imgif_flash_info_t *flashInfoP); + + +#endif /* CMS_IMGIF_NAND_H */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_pkgtb.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_pkgtb.c new file mode 100755 index 00000000000..913a565a320 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_pkgtb.c @@ -0,0 +1,2068 @@ +/***************************************************************************** + * <:copyright-BRCM:2015:DUAL/GPL:standard + * + * Copyright (c) 2015 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ****************************************************************************/ + +/***************************************************************************** +* Description: +* +* The BCM CPE software Image Incremental Flashing (imageIf) library +* implementation. This library runs on top of bcm_flashutil. It uses +* the incremental flashing mechanism to avoid holding the entire image +* in RAM, thus reduces RAM usage. +* This library is expected to be platform-independent. The underlying +* bcm_flashutil library handles the platform-specific operations. +* Notes about the library: +* +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ +#include "bcm_flashutil.h" +#include "bcm_flashutil_nand.h" +#include "bcm_flashutil_emmc.h" +#include "bcm_flashutil_nor.h" + +#include +#include "bcm_imgif.h" + +#include "bcm_imgif_pkgtb.h" +#include "bcmTag.h" +#include "bcm_hwdefs.h" +#include "bcm_boarddriverctl.h" +#include "genutil_crc.h" +#include "bcm_imgutil.h" + +#include +#include +#include +#include + +#include +#include +#include + +/* ---- Constants and Types ----------------------------------------------- */ +#define IMG_WRITE_FS 1 /* Keep enabled: Enable filesystem writing */ +#define CC_IMGIF_DEBUG 0 + +/* Compile flags */ +#define PKGTB_FORKED_WRITES 1 // Fork child processes for writing bootfs/rootfs segments to flash +#define PKGTB_USE_TMP_FILES_ALL 1 // Download entire segments to temp files in /var +#if PKGTB_USE_TMP_FILES_ALL +#define PKGTB_USE_SHELL_SHA256 1 // Use sha256 from linux shell +#else +#define PKGTB_USE_SHELL_SHA256 0 // Do NOT manually change this define! +#endif +#define PKGTB_FLASH_LOADER 1 // Flash the loader binary + +#define PKGTB_UBI_VOL_OVHEAD (1024*1024) + +/* MTD device names */ +#define PKGTB_MTD_IMG_DEV_NAME "image" +#define PKGTB_MTD_LOADER_DEV_NAME "loader" + +/* hash/signature node */ +#define PKGTB_HASH_NODENAME "hash" +#define PKGTB_ALGO_PROP "algo" +#define PKGTB_VALUE_PROP "value" +#define PKGTB_IGNORE_PROP "uboot-ignore" +#define PKGTB_SIG_NODENAME "signature" + +/* image node */ +#define PKGTB_IMAGES_PATH "/images" +#define PKGTB_DATA_PROP "data" +#define PKGTB_DATA_POSITION_PROP "data-position" +#define PKGTB_DATA_OFFSET_PROP "data-offset" +#define PKGTB_DATA_SIZE_PROP "data-size" +#define PKGTB_TIMESTAMP_PROP "timestamp" +#define PKGTB_DESC_PROP "description" +#define PKGTB_ARCH_PROP "arch" +#define PKGTB_TYPE_PROP "type" +#define PKGTB_OS_PROP "os" +#define PKGTB_COMP_PROP "compression" + +/* configuration node */ +#define PKGTB_CONFS_PATH "/configurations" +#define PKGTB_KERNEL_PROP "kernel" +#define PKGTB_RAMDISK_PROP "ramdisk" +#define PKGTB_FDT_PROP "fdt" +#define PKGTB_DEFAULT_PROP "default" + +/* Compat string */ +#define PKGTB_COMPAT_PARAM_DELIM ";" +#define PKGTB_COMPAT_VALUE_DELIM "," +#define PKGTB_COMPAT_VALUE_REF "=" + +/* PKGTB Segment defines */ +#define PKGTB_SEG_IDX_MAX 10 +#define PKGTB_SEG_IDX_INVALID -1 + +/* Partition numbers/volids */ +#define PKGTB_NAND_BOOTFS1_VOLID 3 +#define PKGTB_NAND_ROOTFS1_VOLID 4 +#define PKGTB_NAND_BOOTFS2_VOLID 5 +#define PKGTB_NAND_ROOTFS2_VOLID 6 +#define PKGTB_EMMC_BOOTFS1_VOLID PKGTB_NAND_BOOTFS1_VOLID +#define PKGTB_EMMC_ROOTFS1_VOLID PKGTB_NAND_ROOTFS1_VOLID +#define PKGTB_EMMC_BOOTFS2_VOLID PKGTB_NAND_BOOTFS2_VOLID +#define PKGTB_EMMC_ROOTFS2_VOLID PKGTB_NAND_ROOTFS2_VOLID +#define PKGTB_IMG1_PART_NUM 1 +#define PKGTB_IMG2_PART_NUM 2 + +typedef enum +{ + IMGIF_PKGTB_IMG_SEGMENT_PKGT_HDR = 0, //FDT header + IMGIF_PKGTB_IMG_SEGMENT_PKGT, //Actual full FDT + IMGIF_PKGTB_IMG_SEGMENT_LOADER, + IMGIF_PKGTB_IMG_SEGMENT_ROOTFS, + IMGIF_PKGTB_IMG_SEGMENT_BOOTFS, + IMGIF_PKGTB_IMG_SEGMENT_UNKNOWN, +} IMGIF_PKGTB_IMG_SEGMENTS; + +typedef struct +{ + char * name; + uint64_t data_offset; + uint64_t size; + uint64_t bytesdone; + IMGIF_PKGTB_IMG_SEGMENTS type; + unsigned int valid; + UINT8 * sha256_ptr; +} IMGIF_PKGTB_IMG_SEGMENT_INFO; + +/* IMGIF pkgtb context. */ +typedef struct +{ + FILE * loader_fh; + FILE * rootfs_fh; + FILE * bootfs_fh; + IMGIF_PKGTB_IMG_SEGMENT_INFO pkgtb_img_segments[PKGTB_SEG_IDX_MAX]; + int current_img_segment_idx; + int num_img_segments; + int num_img_segments_complete; + unsigned int crc_image_calc; + uint64_t total_img_bytesdone; + char * pkgt_ptr; + char * loader_ptr; + int loader_seg_index; + int booted_img_idx; + int update_img_idx; + struct fdt_header pkgt_hdr; + imgif_img_info_t imgInfoExt; + IMG_FORMAT_PARSER_CB fmtParserCb; + CAL_CRC32_CB calCrc32Cb; +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + unsigned force_upd_img_idx; +#endif +} imgif_ctx_t; + +#define getCtx() (&imgif_ctx) +#define getCtxByHandle(h) ((imgif_ctx_t*)h) + +#if CC_IMGIF_DEBUG +#define imgif_debug(fmt, arg...) \ + printf("%s.%u: " fmt , __FUNCTION__, __LINE__, ##arg) +#define DUMPIMGIFCTX(cxtP) dump_ctx(ctxP) +#else +#define imgif_debug(fmt, arg...) +#define DUMPIMGIFCTX(cxtP) +#endif + +#define imgif_error(fmt, arg...) \ + printf("ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + +/* ---- Private Function Prototypes --------------------------------------- */ +/* ---- Public Variables -------------------------------------------------- */ +/* ---- Private Variables ------------------------------------------------- */ +static imgif_ctx_t imgif_ctx; +#if PKGTB_FORKED_WRITES +static int forked_flash_writes = 0; +#endif +/* ---- Functions --------------------------------------------------------- */ + +/*********************************************************************************** + * PKTB SEGMENT PROCESSING FUNCTIONS * + ***********************************************************************************/ +#if PKGTB_USE_SHELL_SHA256 +static int compare_imgseg_sha256(const char *imgseg_path, + const UINT8 *imgseg_sha) +{ + FILE *fp; + char cmdBuf[512]={0}; + char output[64+2+sizeof(cmdBuf)+1]={0}; // see comment below about length + + /* Open the command for reading. */ + snprintf(cmdBuf, sizeof(cmdBuf), "sha256sum %s", imgseg_path); + fp = popen(cmdBuf, "r"); + if (fp == NULL) + { + printf("Failed to run command %s\n", cmdBuf); + return -1; + } + + // Example output of sha256sum: + // f15650dac207ad8ef72dff5eefddd910c7cef2b6d33a15f2b2343029cfa45704 + // Sha256 is 32 bytes, which takes 64 bytes to represent in hex. + // So length of output buffer must be 64 + 2 spaces + strlen(path) + null + if (fgets(output, sizeof(output)-1, fp) == NULL) + { + printf("Could not read results of cmd %s\n", cmdBuf); + pclose(fp); + return -1; + } + + // We got the output we need, close fp now. + pclose(fp); + + // Compare output sha256 with expected value in imgseg_sha + { + int rc, i; + UINT8 byte; + + for (i=0; i < 32; i++) + { + rc = sscanf(&(output[i*2]), "%2hhx", &byte); + if (rc != 1) + { + printf("%s: parse failed at [%d] (output=%s)\n", + __FUNCTION__, i*2, output); + return -1; + } + else if (byte != imgseg_sha[i]) + { + printf("%s: compare failed at [%d]: got %2hhx expected %2hhx\n", + __FUNCTION__, i, byte, imgseg_sha[i]); + return -1; + } + } + } + + // if we get here, then sha256sum matched. + return 0; +} +#endif /* PKGTB_USE_SHELL_SHA256 */ + + +static int run_shell_command(const char* cmd) +{ + int status; + int ret = -1; + + status = system(cmd); + + if (-1 == status) + { + imgif_debug("%s: Error: run shell command: %s fail. System error!\n", __FUNCTION__, cmd); + } + else + { + if (WIFEXITED(status)) + { + if (0 == WEXITSTATUS(status)) + { + imgif_debug("%s:run shell command %s successfully.\n",__FUNCTION__,cmd); + ret = 0; + } + else + { + imgif_debug("%s:run shell command %s fail, exit code: %d\n",__FUNCTION__,cmd, WEXITSTATUS(status)); + } + } + else + { + imgif_debug("%s:run shell command %s fail, exit status = [%d]\n",__FUNCTION__, cmd, WEXITSTATUS(status)); + } + } + return ret; +} +static int pivot_rootfs_to_ramfile(const char* ram_file_name) +{ + char cmd[256]; + + //FIXME put commands in a shell script? + /* only return -1 for several important cmd*/ + if( run_shell_command("mkdir /var/ramdisk") ) + return -1; + sprintf(cmd, "mount -o loop %s /var/ramdisk", ram_file_name); + if( run_shell_command(cmd)) + return -1; + run_shell_command("mount --move /var /var/ramdisk/var"); + run_shell_command("mount --move /data /var/ramdisk/data"); + run_shell_command("mount --move /dev /var/ramdisk/dev"); + run_shell_command("mount --move /mnt /var/ramdisk/mnt"); + run_shell_command("mount --move /sys /var/ramdisk/sys"); + run_shell_command("mount --move /proc /var/ramdisk/proc"); + run_shell_command("mount --move /dev/pts /var/ramdisk/dev/pts"); + run_shell_command("mount --move /sys/kernel/debug /var/ramdisk/sys/kernel/debug"); + if( run_shell_command("mkdir /var/ramdisk/var/oldroot")) + return -1; + if( run_shell_command("pivot_root /var/ramdisk/ /var/ramdisk/var/oldroot/")) + return -1; + run_shell_command("umount /var/oldroot/data/"); + run_shell_command("umount /var/oldroot/dev/pts/"); + run_shell_command("umount /var/oldroot/sys/kernel/debug/"); + run_shell_command("umount /var/oldroot/sys/"); + run_shell_command("umount /var/oldroot/proc"); + run_shell_command("umount /var/oldroot/mnt/"); + run_shell_command("rm /dev/root"); + //FIXME maybe need to check which loop device is used,in case it is not /dev/loop0 + run_shell_command("ln -s /dev/loop0 /dev/root"); + run_shell_command("umount /dev/root"); + run_shell_command("mount --move /var/oldroot/var /var"); + + return 0; +} + +static int finalize_tmpfile_write_spinor( int vol_id, char * vol_type, + char* dev_name_prefix, int seg_index, imgif_ctx_t *ctxP ) +{ + char cmd[128]; + char mtd_name[128]; + int ret= -1; + printf("Flashing %s ....\n", dev_name_prefix); + switch( ctxP->pkgtb_img_segments[seg_index].type ) + { + case IMGIF_PKGTB_IMG_SEGMENT_LOADER: + sprintf(cmd, "/var/%s.tmp",dev_name_prefix); + sprintf(mtd_name,"/dev/%s",SPI_NOR_LOADER_MTD); + ret = norWriteFileToMtdPar(cmd,mtd_name); + break; + case IMGIF_PKGTB_IMG_SEGMENT_BOOTFS: + sprintf(cmd, "/var/%s.tmp",dev_name_prefix); + sprintf(mtd_name,"/dev/%s",SPI_NOR_BOOTFS_MTD); + ret = norWriteFileToMtdPar(cmd,mtd_name); + break; + case IMGIF_PKGTB_IMG_SEGMENT_ROOTFS: + sprintf(cmd, "/var/%s.tmp",dev_name_prefix); + if(pivot_rootfs_to_ramfile(cmd)) + { + printf("pivot rootfs FAILED!\n"); + } + else + { + sprintf(mtd_name,"/dev/%s",SPI_NOR_ROOTFS_MTD); + ret = norWriteFileToMtdPar(cmd,mtd_name); + break; + } + break; + default: + break; + } + return ret; +} + +#define EXTRA_SPC_SUFFIX_STR "_extra_space" +static uint64_t nand_get_part_extra_bytes( char * part_prefix ) +{ + char filename[128]; + char value[10]; + int i; + unsigned long long extra_bytes = 0; + unsigned long long size_mult = 1; + FILE *fp = NULL; + + /* Get extra bytes specified in env */ + sprintf(filename, "/proc/environment/%s%s", part_prefix, + EXTRA_SPC_SUFFIX_STR); + + if( access( filename, F_OK ) != -1 ) + { + if ((fp = fopen(filename, "r")) == NULL) + { + printf("could not open %s", filename); + return 0; + } + + if( NULL == fgets(value, 10, fp) ) + { + printf("Could not read %s", filename); + fclose(fp); + return 0; + } + fclose(fp); + + /* Parse extra bytes string */ + for( i=0; i< strlen(value); i++) + { + switch(value[i]) { + case 'k': + case 'K': + size_mult = 1024; + value[i] = '\0'; + break; + + case 'm': + case 'M': + size_mult = 1024*1024; + value[i] = '\0'; + break; + + case 'g': + case 'G': + size_mult = 1024*1024*1024; + value[i] = '\0'; + break; + + } + if( size_mult > 1) + break; + } + extra_bytes = strtoull(value, NULL, 10) * size_mult; + } + else + + if(extra_bytes < PKGTB_UBI_VOL_OVHEAD ) + extra_bytes = PKGTB_UBI_VOL_OVHEAD; + + return extra_bytes; +} + +static int finalize_tmpfile_write_nand( int vol_id, char * vol_type, + char* dev_name_prefix, int seg_index, imgif_ctx_t *ctxP ) +{ + char cmd[128]; + int ret= -1; + printf("Flashing %s ....\n", dev_name_prefix); + if( ctxP->pkgtb_img_segments[seg_index].type == IMGIF_PKGTB_IMG_SEGMENT_LOADER ) + { +#if CC_IMGIF_DEBUG + sprintf(cmd, "cp /var/%s.tmp /var/%s.tmp_cooked", dev_name_prefix, dev_name_prefix); + imgif_debug("%s\n", cmd); + ret = system(cmd); +#endif /* CC_IMGIF_DEBUG */ + sprintf(cmd, "/var/%s.tmp",dev_name_prefix); + + /* Flash loader */ + ret = nandFlashLoader((unsigned char*)cmd, ctxP->pkgtb_img_segments[seg_index].size); + } + else + { + /* Delete update ubi volume */ + sprintf(cmd, "/dev/ubi0_%d", vol_id) ; + if( access( cmd, F_OK ) != -1 ) + { + /* If volume exists then delete it first */ + sprintf(cmd, "ubirmvol /dev/ubi0 -n %d", vol_id) ; + imgif_debug("%s\n", cmd); + ret = system(cmd); + } + else + ret = 0; + + if( ret ) + return ret; + + /* Create update ubi volume */ + sprintf(cmd, "ubimkvol /dev/ubi0 -s %llu -n %d -N %s%d --type=%s", + (unsigned long long) (ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone + nand_get_part_extra_bytes(dev_name_prefix)), + vol_id, dev_name_prefix, ctxP->update_img_idx, vol_type) ; + imgif_debug("%s\n", cmd); + ret = system(cmd); + + if( ret ) + return ret; + + /* Update volume with img data */ + sprintf(cmd, "/dev/ubi0_%d", vol_id) ; + if( nandUbiVolDevNodeExists(cmd) ) + { + /* update ubi volume if it exists*/ + sprintf(cmd, "ubiupdatevol /dev/ubi0_%d /var/%s.tmp", vol_id, dev_name_prefix); + imgif_debug("%s\n", cmd); + ret = system(cmd); + } + else + { + printf("%s: Error: Ubi volume %s does not exist!\n", __FUNCTION__, cmd); + ret = -1; + return ret; + } + } + return ret; +} + +static int finalize_tmpfile_write_emmc( int vol_id, char * vol_type, + char* dev_name_prefix, int seg_index, imgif_ctx_t *ctxP ) +{ + char cmd[128]; + char dev_name[64]; + int ret= -1; + char * block_size; + int mmc_boot_part = 0; + + printf("Flashing %s to ", dev_name_prefix); + if( ctxP->pkgtb_img_segments[seg_index].type == IMGIF_PKGTB_IMG_SEGMENT_LOADER ) + { + mmc_boot_part = emmcGetBootPartIndex(); + sprintf(cmd, "echo 0 > /sys/block/mmcblk0boot%d/force_ro", mmc_boot_part); + ret = system(cmd); + sprintf(dev_name, "/dev/mmcblk0boot%d", mmc_boot_part); + + /* Write loader block by block, 512 bytes at a time */ + block_size = "bs=512"; + } + else + sprintf(dev_name, "/dev/%s%d", dev_name_prefix, ctxP->update_img_idx); + + printf("%s ....\n", dev_name); + + sprintf(cmd, "dd if=/var/%s.tmp of=%s %s 2>&1", dev_name_prefix, dev_name, block_size); + imgif_debug("%s\n", cmd); + ret = system(cmd); + + ret = system("sync"); + return ret; +} + +static int finalize_tmpfile_write( int seg_index, imgif_ctx_t *ctxP ) +{ + char * dev_name_prefix = NULL; + char * vol_type = NULL; + int vol_id = 0; + char cmd[128]; + int ret = 0; + pid_t child_pid = 0; + imgif_flash_info_t flashInfo; + + imgif_pkgtb_get_flash_info(&flashInfo); + switch(ctxP->pkgtb_img_segments[seg_index].type) + { + case IMGIF_PKGTB_IMG_SEGMENT_ROOTFS: + /* If rootfs complete, write it to flash */ + dev_name_prefix = "rootfs"; + if (flashInfo.flashType != FLASH_INFO_FLAG_NOR) + { + vol_id = (ctxP->update_img_idx == PKGTB_IMG1_PART_NUM? + PKGTB_NAND_ROOTFS1_VOLID:PKGTB_NAND_ROOTFS2_VOLID); + vol_type = "dynamic"; + } + break; + + case IMGIF_PKGTB_IMG_SEGMENT_BOOTFS: + /* If bootfs complete, write it to flash */ + dev_name_prefix = "bootfs"; + if(flashInfo.flashType != FLASH_INFO_FLAG_NOR) + { + vol_id = (ctxP->update_img_idx == PKGTB_IMG1_PART_NUM? + PKGTB_NAND_BOOTFS1_VOLID:PKGTB_NAND_BOOTFS2_VOLID); + vol_type = "static"; + } + break; + + case IMGIF_PKGTB_IMG_SEGMENT_LOADER: + /* If loader complete, write it to flash */ + dev_name_prefix = "loader"; + break; + + default: + printf("%s: Nothing to do for segment! %d\n", __FUNCTION__, + seg_index); + return 0; + break; + } + + sprintf(cmd, "/var/%s.tmp", dev_name_prefix); +#if PKGTB_USE_SHELL_SHA256 + printf("\nVerifying SHA256 of %s ........", ctxP->pkgtb_img_segments[seg_index].name); + if( compare_imgseg_sha256(cmd , ctxP->pkgtb_img_segments[seg_index].sha256_ptr) == 0 ) + printf("OK!\n"); + else + { + printf("FAILED!\n"); + return -1; + } +#endif + +#if PKGTB_FLASH_LOADER + /* Since loader is the last segment to be flashed, sync environment settings */ + if( ctxP->pkgtb_img_segments[seg_index].type == IMGIF_PKGTB_IMG_SEGMENT_LOADER ) + { + ret = synchLoaderEnv( cmd ); + } + else +#endif /* PKGTB_FLASH_LOADER */ + { +#if PKGTB_FORKED_WRITES + child_pid = fork(); + if( child_pid >= 0 ) + { + if( child_pid > 0 ) + { + printf("%s: Child PID %ld launched for flashing seg %d (%s)\n", + __FUNCTION__, (long)child_pid, seg_index, + ctxP->pkgtb_img_segments[seg_index].name); + + forked_flash_writes++; + } + } + else + { + printf("%s: Error launching Child for flashing segment %d \n",__FUNCTION__, seg_index); + return -1; + } +#endif + } + + /* Call flash specific routines */ + if( child_pid == 0 ) + { + if( ret == 0 ) + { + imgif_pkgtb_get_flash_info(&flashInfo); + switch( flashInfo.flashType ) + { + case FLASH_INFO_FLAG_NAND: + ret = finalize_tmpfile_write_nand(vol_id, vol_type, dev_name_prefix, seg_index, ctxP); + break; + case FLASH_INFO_FLAG_EMMC: + ret = finalize_tmpfile_write_emmc(vol_id, vol_type, dev_name_prefix, seg_index, ctxP); + break; + case FLASH_INFO_FLAG_NOR: + ret = finalize_tmpfile_write_spinor(vol_id, vol_type, dev_name_prefix, seg_index, ctxP); + break; + default: + break; + } + } + if( ret ) +#if PKGTB_FORKED_WRITES + printf("%s: Failed to flash segment %d. Child PID %ld, ret %d!!\n", __FUNCTION__, seg_index, (long)getpid(), ret); +#else + printf("%s: Failed to flash segment %d. ret %d!!\n", __FUNCTION__, seg_index, ret); +#endif + + /* Delete temp file */ + /*For SPI nor, dont delete rootfs tmp file*/ + if( (flashInfo.flashType != FLASH_INFO_FLAG_NOR) || (ctxP->pkgtb_img_segments[seg_index].type != IMGIF_PKGTB_IMG_SEGMENT_ROOTFS)) + { + sprintf(cmd,"rm -f /var/%s.tmp", dev_name_prefix); + system(cmd); + } +#if PKGTB_FORKED_WRITES + /* Exit child process if not flashing loader */ + if( ctxP->pkgtb_img_segments[seg_index].type != IMGIF_PKGTB_IMG_SEGMENT_LOADER ) + { + if( ret ) + ret = EXIT_FAILURE; + else + ret = EXIT_SUCCESS; + + _exit(ret); + } +#endif + return ret; + } + else + return ret; +} + +static void print_imgupdate_progress( imgif_ctx_t * ctxP) +{ +#if CC_IMGIF_DEBUG + int i = 0; + int size = 0; + int bytes_done = 0; + + for( i=0; ipkgtb_img_segments[i].size; + bytes_done += ctxP->pkgtb_img_segments[i].bytesdone; + } + printf("\rImage Update Progress: %d/%d bytes\n", bytes_done, size); +#else + fprintf(stderr, "."); +#endif +} + +static int process_pkgt_hdr( imgif_ctx_t *ctxP) +{ + int pkgt_size = 0; + int ret = fdt_check_header(&ctxP->pkgt_hdr); + if(ret) + { + printf("Invalid FDT hdr check failed:%d! Aborting!\n", ret); + } + else + { + /* Allocate space for entire pkgt */ + pkgt_size = fdt_totalsize(&ctxP->pkgt_hdr); + ctxP->pkgt_ptr = malloc(pkgt_size); + memcpy(ctxP->pkgt_ptr, &(ctxP->pkgt_hdr), sizeof(struct fdt_header)); + + /* Add another segment to handle actual pgkt */ + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+1].name = "PKGT"; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+1].size = pkgt_size; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+1].data_offset = 0; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+1].bytesdone = sizeof(struct fdt_header); + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+1].type = IMGIF_PKGTB_IMG_SEGMENT_PKGT; + ctxP->num_img_segments++; + +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Initialize SHA256 for current segment +#endif + } + return ret; +} + +static int process_pkgt_img_segments( imgif_ctx_t *ctxP ) +{ + int images_noffset, noffset_hash; + int noffset; + int ndepth; + int count; +#if CC_IMGIF_DEBUG + int len; + char* desc; +#endif + unsigned int data_size, data_offset; + const fdt32_t *val; + int ret = 0; + const char * hash_name = NULL; + UINT8* sha256_ptr = NULL; + + /* Find images parent node offset */ + ret = fdt_check_header(ctxP->pkgt_ptr); + if(ret) + { + printf("Invalid FDT hdr check failed:%d! Aborting!\n", ret); + } + + images_noffset = fdt_path_offset(ctxP->pkgt_ptr, PKGTB_IMAGES_PATH); + if (images_noffset < 0) { + printf("Can't find images parent node '%s' (%s)\n", + PKGTB_IMAGES_PATH, fdt_strerror(images_noffset)); + return -1; + } + + /* Process all image subnodes */ + for (ndepth = 0, count = 0, + noffset = fdt_next_node(ctxP->pkgt_ptr, images_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0) && ctxP->num_img_segments < PKGTB_SEG_IDX_MAX; + noffset = fdt_next_node(ctxP->pkgt_ptr, noffset, &ndepth)) + { + if (ndepth == 1) + { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + imgif_debug("Found Image %u (%s): ", count, + fdt_get_name(ctxP->pkgt_ptr, noffset, NULL)); + printf("\n"); + + /* Description */ +#if CC_IMGIF_DEBUG + desc = (char *)fdt_getprop(ctxP->pkgt_ptr, noffset, PKGTB_DESC_PROP, &len); + imgif_debug(" Description: "); + if (ret) + imgif_debug("unavailable\n"); + else + imgif_debug("%s\n", desc); +#endif + + /* Offset - Check for both relative and absolute offsets */ + val = fdt_getprop(ctxP->pkgt_ptr, noffset, PKGTB_DATA_OFFSET_PROP, NULL); + if( val ) + { + /* Relative offset */ + data_offset = fdt32_to_cpu(*val); + data_offset += ((fdt_totalsize(ctxP->pkgt_ptr) + 3) & ~3); + } + else + { + val = fdt_getprop(ctxP->pkgt_ptr, noffset, PKGTB_DATA_POSITION_PROP, NULL); + if (!val) + return -1; + + /* Absolute offset */ + data_offset = fdt32_to_cpu(*val); + } + + /* Size */ + val = fdt_getprop(ctxP->pkgt_ptr, noffset, PKGTB_DATA_SIZE_PROP, NULL); + if (!val) + return -1; + + data_size = fdt32_to_cpu(*val); + imgif_debug(" Offset:0x%08x Size:0x%08x\n", data_offset, data_size); + count++; + + /* Get hash value */ + fdt_for_each_subnode(noffset_hash, ctxP->pkgt_ptr, noffset) + { + hash_name = fdt_get_name(ctxP->pkgt_ptr, noffset_hash, NULL); + if (!strncmp(hash_name, PKGTB_HASH_NODENAME, strlen(PKGTB_HASH_NODENAME))) + { + sha256_ptr = (uint8_t *)fdt_getprop(ctxP->pkgt_ptr, noffset_hash, PKGTB_VALUE_PROP, NULL); + } + } + + /* Add segment */ + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+count].name = (char*)fdt_get_name(ctxP->pkgt_ptr, noffset, NULL); + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+count].size = data_size; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+count].data_offset = data_offset; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+count].bytesdone = 0; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+count].type = IMGIF_PKGTB_IMG_SEGMENT_UNKNOWN; + if( hash_name && sha256_ptr ) + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx+count].sha256_ptr = sha256_ptr; + +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Initialize SHA256 for current segment +#endif + ctxP->num_img_segments++; + } + } + return 0; +} + +static void dump_img_segments( imgif_ctx_t * ctxP ) +{ + int i; + + printf("PKGTB update image detected. Image Segments found:\n"); + for( i=0; inum_img_segments; i++ ) + { + printf(" [%d] %s --> offset:0x%08x, size:0x%08x, type:%d\n", + i, + ctxP->pkgtb_img_segments[i].name, + (unsigned int)ctxP->pkgtb_img_segments[i].data_offset, + (unsigned int)ctxP->pkgtb_img_segments[i].size, + ctxP->pkgtb_img_segments[i].type); + } + printf("Current_img_idx: %d, Update_img_idx: %d\n", ctxP->booted_img_idx, ctxP->update_img_idx); +} + +static int select_pkgt_img_segments( imgif_ctx_t *ctxP, char * name, IMGIF_PKGTB_IMG_SEGMENTS type ) +{ + int i; + + for( i=0; inum_img_segments; i++ ) + { + if ( strcmp(ctxP->pkgtb_img_segments[i].name, name) == 0 ) + { + ctxP->pkgtb_img_segments[i].type = type; + return i; + } + } + return PKGTB_SEG_IDX_INVALID; +} + +static FILE * init_storage_dev( char * dev_name_prefix, int seg_index, imgif_ctx_t *ctxP) +{ + char file_name[128]; +#if PKGTB_USE_TMP_FILES_ALL + /* Open temp files for all binaries */ + sprintf(file_name, "/var/%s.tmp", dev_name_prefix); + imgif_debug("Opening file %s for writing\n", file_name ); + return(fopen(file_name, "w")); +#else + switch(ctxP->pkgtb_img_segments[seg_index].type) + { + case IMGIF_PKGTB_IMG_SEGMENT_LOADER: + /* loader will still need a temp file */ + sprintf(file_name, "/var/%s.tmp", dev_name_prefix); + imgif_debug("Opening file %s for writing\n", file_name ); + return(fopen(file_name, "w")); + break; + + case IMGIF_PKGTB_IMG_SEGMENT_ROOTFS: + case IMGIF_PKGTB_IMG_SEGMENT_BOOTFS: + //FIXME: Replace with actual deleting/opening of flash device for rootfs/bootfs + break; + + default: + break; + } + return NULL; +#endif +} + +static int check_compat_prop(char * prop, char * values) +{ + int ret = -1; + imgif_flash_info_t flashInfo; + char blksize[128]; + char * tmp = NULL; + if( strcmp(prop, "chip") == 0 ) + { + /* Check if socname matches */ + if( bcmImg_MatchChipId(values) ) + ret = 0; + + if( ret ) + printf("%s: Error! chipid check failed\n", __FUNCTION__); + } + else if( strcmp(prop, "flash") == 0 ) + { + /* Check if flash type matches */ + imgif_pkgtb_get_flash_info(&flashInfo); + switch( flashInfo.flashType ) + { + case FLASH_INFO_FLAG_NAND: + if( (tmp = strstr(values, "nand")) ) + { + /* Check if there is a blksize appended */ + tmp += strlen("nand"); + if( '9' >= *tmp && *tmp >= '0' ) + { + sprintf(blksize, "%d", flashInfo.eraseSize/1024); + if( strstr(values, blksize) ) + ret = 0; + } + else + ret = 0; + } + + if( ret ) + printf("%s: Error! Invalid img flash format:%s, supported format:nand%d\n", + __FUNCTION__, values, flashInfo.eraseSize/1024); + + break; + case FLASH_INFO_FLAG_EMMC: + if( strstr(values, "emmc") ) + ret = 0; + if( ret ) + printf("%s: Error! Invalid img flash format:%s, supported format:emmc\n", + __FUNCTION__, values); + break; + case FLASH_INFO_FLAG_NOR: + if( strstr(values, "nor") ) + ret = 0; + + if( ret ) + printf("%s: Error! Invalid img flash format:%s, supported format:nor\n", + __FUNCTION__, values); + break; + + default: + break; + } + } + else if( strcmp(prop, "rev") == 0 ) + { + /* Check chip rev */ + ret = 0; + } + else if( strcmp(prop, "fstype") == 0 ) + { + /* Check filesystem type compatibility */ + ret = 0; + } + else if( strcmp(prop, "ddr") == 0 ) + { + /* Check ddr compatibility */ + ret =0; + } + else + { + ret = 0; + } + + return ret; +} + +size_t strlcpy(char *dst, const char *src, size_t size) +{ + size_t srclen, len; + + srclen = strlen(src); + if (size <= 0) + return srclen; + + len = (srclen < size) ? srclen : size - 1; + memcpy(dst, src, len); /* should not overlap */ + dst[len] = '\0'; + + return srclen; +} + +int check_pkgtb_compat_string( char* compat_str ) +{ + char * token; + char * prop; + char * values; + char * comp_str_buf = NULL; + int ret = 0; + int msize; + + msize = strlen(compat_str); + comp_str_buf = malloc(msize); + memset(comp_str_buf, 0, msize); + + if( comp_str_buf ) + { + strlcpy(comp_str_buf, compat_str, msize); + imgif_debug("Comp_str: %s\n", comp_str_buf); + token = strtok(comp_str_buf, PKGTB_COMPAT_PARAM_DELIM); + while (token != NULL && !ret) + { + imgif_debug("Param: %s\n", token); + prop = token; + values = strstr(token, PKGTB_COMPAT_VALUE_REF)+1; + *(values-1) = '\0'; + imgif_debug(" prop:%s values:%s\n", prop, values); + ret = check_compat_prop(prop, values); + token = strtok(NULL, ";"); + } + if( ret ) + printf("%s: Error! Image compatibility check FAILS! Aborting upgrade!\n", __FUNCTION__); + + free(comp_str_buf); + } + else + printf("%s: Error! Cannot allocate memory for compat string! Aborting upgrade!\n", __FUNCTION__); + + return ret; +} + +static int process_pkgt( imgif_ctx_t *ctxP ) +{ + char * desc_ptr; + int conf_noffset; + int len; + char path[128]; + int seg_index = 0; + uint64_t bootfs_rootfs_size = 0; + uint64_t loader_size = 0; + uint64_t avail_space = 0; + int valid_flag; + uint64_t bootfs_size = 0; + uint64_t rootfs_size = 0; + imgif_flash_info_t flashInfo; + + imgif_pkgtb_get_flash_info(&flashInfo); + + /* Iterate through all images and record their offsets and sizes */ + if( process_pkgt_img_segments( ctxP ) < 0 ) + return -1; + + /* Identify and select the segments we want via default configuration */ + conf_noffset = fdt_path_offset(ctxP->pkgt_ptr, PKGTB_CONFS_PATH); + if (conf_noffset < 0) { + printf("Can't find images parent node '%s' (%s)\n", + PKGTB_CONFS_PATH, fdt_strerror(conf_noffset)); + return -1; + } + + /* Get default configuration */ + desc_ptr = (char *)fdt_getprop(ctxP->pkgt_ptr, conf_noffset, PKGTB_DEFAULT_PROP, &len); + if(desc_ptr) + { + imgif_debug("Default Configuration: %s\n", desc_ptr); + sprintf(path,"%s/%s",PKGTB_CONFS_PATH,desc_ptr); + conf_noffset = fdt_path_offset(ctxP->pkgt_ptr,path); + if (conf_noffset < 0) { + printf("Can't find configuration node '%s' (%s)\n", + path, fdt_strerror(conf_noffset)); + return -1; + } + + /* Check compatibility string */ + desc_ptr = (char *)fdt_getprop(ctxP->pkgt_ptr, conf_noffset, "compatible", &len); + if(desc_ptr) + { + if(check_pkgtb_compat_string(desc_ptr)) + return -1; + } + else + { + printf("%s: Error! Missing compatibility string! Cannot determine SoC name!\n", __FUNCTION__); + return -1; + } + + /* Get bootfs */ + desc_ptr = (char *)fdt_getprop(ctxP->pkgt_ptr, conf_noffset, "bootfs", &len); + if(desc_ptr) + { + imgif_debug(" bootfs: %s\n", desc_ptr); + seg_index = select_pkgt_img_segments( ctxP, desc_ptr, IMGIF_PKGTB_IMG_SEGMENT_BOOTFS); + if( flashInfo.flashType == FLASH_INFO_FLAG_NOR ) + bootfs_size += ctxP->pkgtb_img_segments[seg_index].size; + else + bootfs_rootfs_size += ctxP->pkgtb_img_segments[seg_index].size + nand_get_part_extra_bytes("bootfs"); + ctxP->bootfs_fh = init_storage_dev("bootfs", seg_index, ctxP); + if( !ctxP->bootfs_fh ) + { + printf("%s: Error! Cant open file for bootfs flashing!\n", __FUNCTION__); + return -1; + } + } + + /* Get rootfs */ + desc_ptr = (char *)fdt_getprop(ctxP->pkgt_ptr, conf_noffset, "rootfs", &len); + if(desc_ptr) + { + imgif_debug(" rootfs: %s\n", desc_ptr); + seg_index = select_pkgt_img_segments( ctxP, desc_ptr, IMGIF_PKGTB_IMG_SEGMENT_ROOTFS); + if( flashInfo.flashType == FLASH_INFO_FLAG_NOR ) + rootfs_size += ctxP->pkgtb_img_segments[seg_index].size; + else + bootfs_rootfs_size += ctxP->pkgtb_img_segments[seg_index].size + nand_get_part_extra_bytes("rootfs") ; + ctxP->rootfs_fh = init_storage_dev("rootfs", seg_index, ctxP); + if( !ctxP->rootfs_fh ) + { + printf("%s: Error! Cant open file for rootfs flashing!\n", __FUNCTION__); + return -1; + } + } + + /* Get loader */ + desc_ptr = (char *)fdt_getprop(ctxP->pkgt_ptr, conf_noffset, "loader", &len); + if(desc_ptr) + { + imgif_debug(" loader: %s\n", desc_ptr); + seg_index = select_pkgt_img_segments( ctxP, desc_ptr, IMGIF_PKGTB_IMG_SEGMENT_LOADER); + loader_size += ctxP->pkgtb_img_segments[seg_index].size; + ctxP->loader_ptr = malloc(ctxP->pkgtb_img_segments[seg_index].size); + ctxP->loader_fh = init_storage_dev("loader", seg_index, ctxP); + if( !ctxP->loader_fh || !ctxP->loader_ptr ) + { + if( !ctxP->loader_ptr ) + printf("%s: Error! Cant alloc memory for loader flashing!\n", __FUNCTION__); + else + { + printf("%s: Error! Cant open file for loader flashing!\n", __FUNCTION__); + free(ctxP->loader_ptr); + ctxP->loader_ptr = NULL; + } + return -1; + } + ctxP->loader_seg_index = seg_index; + } + else + ctxP->loader_seg_index = PKGTB_SEG_IDX_INVALID; + + /* We know all sizes now, determine if it will fit in flash */ + if( flashInfo.flashType == FLASH_INFO_FLAG_NOR ) + { + if(rootfs_size) + { + avail_space = spinorGetAvailSpace(SPI_NOR_ROOTFS_MTD); + if ( rootfs_size > avail_space) + { + printf("%s: Error! rootfs MTD partition too small for new rootfs!\n", + __FUNCTION__); + printf("%s: Required space:%llu, Available space:%llu\n", __FUNCTION__, + (unsigned long long)rootfs_size, (unsigned long long)avail_space); + if( loader_size ) + { + free(ctxP->loader_ptr); + ctxP->loader_ptr = NULL; + } + return -1; + } + } + if(bootfs_size) + { + avail_space = spinorGetAvailSpace(SPI_NOR_BOOTFS_MTD); + if ( bootfs_size > avail_space) + { + printf("%s: Error! bootfs MTD partition too small for new bootfs !\n", + __FUNCTION__); + printf("%s: Required space:%llu, Available space:%llu\n", __FUNCTION__, + (unsigned long long)bootfs_size, (unsigned long long)avail_space); + if( loader_size ) + { + free(ctxP->loader_ptr); + ctxP->loader_ptr = NULL; + } + return -1; + } + } + } + else + { + if( bootfs_rootfs_size ) + { + avail_space = getAvailImgSpace(ctxP->update_img_idx); + if( bootfs_rootfs_size > avail_space) + { + printf("%s: Error! image partition(s) too small for new bootfs and rootfs!\n", + __FUNCTION__); + printf("%s: Required space:%llu, Available space:%llu\n", __FUNCTION__, + (unsigned long long)bootfs_rootfs_size, (unsigned long long)avail_space); + if( loader_size ) + { + free(ctxP->loader_ptr); + ctxP->loader_ptr = NULL; + } + return -1; + } + } + } + + /* Check if loader will fit */ + if( loader_size ) + { + avail_space = getAvailLoaderSpace(ctxP->update_img_idx); + if( loader_size > avail_space ) + { + printf("%s: Error! loader MTD partition too small for new loader binary!\n", + __FUNCTION__); + free(ctxP->loader_ptr); + ctxP->loader_ptr = NULL; + return -1; + } + } + + /* Display all parsed segments */ + dump_img_segments(ctxP); + + /* Clear valid flag in metadata for new image */ + //FIXME SPI nor only support single image + if( flashInfo.flashType != FLASH_INFO_FLAG_NOR) + { + valid_flag = 0; + setImgValidStatus(ctxP->update_img_idx, &valid_flag); + } + } + else + { + printf("%s: Error Default configurations not found in upgrade image!\n", __FUNCTION__); + return -1; + } + + return 0; +} + +static int handle_segment_completion( imgif_ctx_t *ctxP ) +{ + FILE * fh = NULL; + int ret = 0; + + ctxP->num_img_segments_complete++; + + switch(ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].type) + { + case IMGIF_PKGTB_IMG_SEGMENT_PKGT_HDR: + /* If we have the pkgt header, process its contents */ + return(process_pkgt_hdr(ctxP)); + + case IMGIF_PKGTB_IMG_SEGMENT_PKGT: + /* We now have full pkgt, process it and setup other segments */ + return(process_pkgt(ctxP)); + + case IMGIF_PKGTB_IMG_SEGMENT_LOADER: + /* Loader is cached until all other segments have been flashed */ +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Compare incr SHA of loader +#endif + break; + + case IMGIF_PKGTB_IMG_SEGMENT_ROOTFS: + /* If rootfs complete, write it to flash */ + fh = ctxP->rootfs_fh; + ctxP->rootfs_fh = NULL; +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Compare incr SHA of ROOTFS +#endif + break; + + case IMGIF_PKGTB_IMG_SEGMENT_BOOTFS: + /* If bootfs complete, write it to flash */ + fh = ctxP->bootfs_fh; + ctxP->bootfs_fh = NULL; +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Compare incr SHA of BOOTFS +#endif + break; + + default: + printf("%s: Nothing to do for segment! %d\n", __FUNCTION__, + ctxP->current_img_segment_idx); + break; + } + + /* Close file*/ + if( fh ) + { + ret = system("sync"); + fclose(fh); + +#if PKGTB_USE_TMP_FILES_ALL + ret = finalize_tmpfile_write( ctxP->current_img_segment_idx, ctxP ); +#endif + } + return ret; +} + +static int finalize_loader( imgif_ctx_t *ctxP ) +{ + int ret = 0; +#if PKGTB_FLASH_LOADER + /* Write loader data */ + imgif_debug("Writing %llu bytes of loader to file:%p\n", + (unsigned long long)ctxP->pkgtb_img_segments[ctxP->loader_seg_index].bytesdone, (ctxP->loader_fh)); + fwrite(ctxP->loader_ptr, 1, ctxP->pkgtb_img_segments[ctxP->loader_seg_index].bytesdone, + ctxP->loader_fh); +#endif /* PKGTB_FLASH_LOADER */ + + if( ferror(ctxP->loader_fh) + || feof(ctxP->loader_fh) ) + { + printf("%s: Error writing segment %d\n", + __FUNCTION__, ctxP->loader_seg_index); + ret = -1; + } + else + { + fclose(ctxP->loader_fh); + ctxP->loader_fh = NULL; +#if PKGTB_FLASH_LOADER + ret = finalize_tmpfile_write( ctxP->loader_seg_index, ctxP ); +#endif + } + return ret; +} + +/*********************************************************************************** + * PKGTB IMGIF FUNCTIONS * + ***********************************************************************************/ + +/***************************************************************************** +* FUNCTION: init_ctx +* PURPOSE: initialize pkgtb img write parameters +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int init_ctx(imgif_ctx_t *ctxP) +{ + int ret=-1; + imgif_flash_info_t flashInfo; + + /* Initialize image segment values */ + ctxP->current_img_segment_idx = 0; + ctxP->num_img_segments = 1; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].name = "PKGT_HDR"; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].size = sizeof(struct fdt_header); + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].data_offset = 0; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone = 0; + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].type = IMGIF_PKGTB_IMG_SEGMENT_PKGT_HDR; + + /* Initialize whole image crc */ + if (ctxP->calCrc32Cb != NULL) + ctxP->calCrc32Cb(0, &ctxP->crc_image_calc, NULL, 0); + +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Initialize SHA256 for current segment +#endif + + /* Initialize image size */ + ctxP->total_img_bytesdone = 0; + + /* Get boot partition */ + //FIXME only support single image for spinor + imgif_pkgtb_get_flash_info(&flashInfo); + if( flashInfo.flashType == FLASH_INFO_FLAG_NOR ) + { + ctxP->booted_img_idx = 1; + ctxP->update_img_idx = 1; + } + else + { + ret = getBootPartition(); + if( ret == -1 ) + { + printf("%s: Error while retrieving boot partition number!\n", __FUNCTION__); + return ret; + } + else + { + ctxP->booted_img_idx = ret; + ctxP->update_img_idx = (ctxP->booted_img_idx==PKGTB_IMG1_PART_NUM)? + PKGTB_IMG2_PART_NUM:PKGTB_IMG1_PART_NUM; + } + } + +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + if (ctxP->force_upd_img_idx) { + ctxP->update_img_idx = ctxP->force_upd_img_idx; + printf("%s: Single Image: Force to boote image 1 , update image to %d !!\n", __FUNCTION__, ctxP->update_img_idx); + } +#endif + + return 0; +} + +/***************************************************************************** +* FUNCTION: deinit_ctx +* PURPOSE: free all pkgtb image write related resources +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int deinit_ctx(imgif_ctx_t *ctxP) +{ + imgif_debug("Closing all files\n"); + +#if IMG_WRITE_FS + /* Close all open files */ + if(ctxP->loader_fh) + fclose(ctxP->loader_fh); + if(ctxP->rootfs_fh) + fclose(ctxP->rootfs_fh); + if(ctxP->bootfs_fh) + fclose(ctxP->bootfs_fh); +#endif + + imgif_debug("Freeing all allocated memory\n"); + + /* Free allocated memory */ + if( ctxP->loader_ptr ) + free(ctxP->loader_ptr); + + if( ctxP->pkgt_ptr ) + free(ctxP->pkgt_ptr); + + /* Clear context */ + memset(ctxP, 0, sizeof(imgif_ctx_t)); + ctxP->loader_seg_index = PKGTB_SEG_IDX_INVALID; + ctxP->current_img_segment_idx = PKGTB_SEG_IDX_INVALID; + return 0; +} + +/***************************************************************************** +* FUNCTION: write_bytes_to_pkgtb_device +* PURPOSE: write bytes to pkgtb devices +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* data (IN) - data pointer +* pktbuf_num_bytes (IN) - number of bytes to write +* RETURNS: +* >0 - number of bytes written +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int write_bytes_to_pkgtb_device( imgif_ctx_t *ctxP, char * data, unsigned int pktbuf_num_bytes ) +{ + unsigned int bytes_left, bytes_to_write; + unsigned int written_bytes = 0; + unsigned int pktbuf_segdata_offset = 0; + char * datap = data; + char * dest_ptr = NULL; + FILE * dest_fh = NULL; + + imgif_debug("num_bytes:%d\n", pktbuf_num_bytes); + + while( pktbuf_num_bytes ) + { + /* Start processing writes */ + imgif_debug("segment:%d, type:%d, seg_bytes_done:%llu/%llu, written_bytes:%d/%d\n", + ctxP->current_img_segment_idx, + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].type, + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone, + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].size, + written_bytes, + pktbuf_num_bytes+written_bytes); + + /* Check if data for current segment lies in current pktbuf_num_bytes */ + if( (ctxP->current_img_segment_idx < ctxP->num_img_segments) + && (ctxP->total_img_bytesdone + pktbuf_num_bytes > ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].data_offset) ) + { + /* Data for current segment lies in current chunk of pktbuf_num_bytes */ + if( ctxP->total_img_bytesdone >= ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].data_offset ) + pktbuf_segdata_offset = 0; + else + pktbuf_segdata_offset = ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].data_offset - ctxP->total_img_bytesdone; + + /* Calculate how many bytes left to copy for segment */ + bytes_left = ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].size + - ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone; + + /* Calculate how many bytes we can actually write */ + bytes_to_write = (bytes_left <= (pktbuf_num_bytes-pktbuf_segdata_offset))? bytes_left:(pktbuf_num_bytes-pktbuf_segdata_offset); + imgif_debug("segment_offs:%llu, segdata_offs:%d, bytes_to_write:%d\n", + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].data_offset, + pktbuf_segdata_offset, + bytes_to_write); + } + else + { + if( ctxP->current_img_segment_idx >= ctxP->num_img_segments ) + { + /* If all image data segments have have been written, but still need + * to write more bytes this means that image may be corrupted (may + * possibly happen if there is extra padding added to end of file). + */ + + printf("%s: Error: Attempt to write %d unknown img data bytes to invalid segment!\n", + __FUNCTION__, pktbuf_num_bytes); + return -1; + } + else + { + /* Data for segment is not in current pktbuf_num_bytes, therefore just consume bytes */ + imgif_debug("CONSUMING %d bytes\n", pktbuf_num_bytes); + } + + /* Do whole image crc on all data */ + if (ctxP->calCrc32Cb != NULL) + { + ctxP->calCrc32Cb(1, &ctxP->crc_image_calc, (unsigned char*)datap, pktbuf_num_bytes); + imgif_debug("crc img tally:0x%08x\n", ctxP->crc_image_calc); + } + + /* Increment our counters by pktbuf_num_bytes and quit loop */ + datap += pktbuf_num_bytes; + written_bytes += pktbuf_num_bytes; + ctxP->total_img_bytesdone += pktbuf_num_bytes; + pktbuf_num_bytes = 0; + pktbuf_segdata_offset = 0; + continue; + } + + /* Figure out whether we need to cache the segment data in memory or write it to fs */ + switch(ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].type) + { + case IMGIF_PKGTB_IMG_SEGMENT_PKGT_HDR: + /* Copy to local buffer */ + dest_ptr = (char*)&(ctxP->pkgt_hdr); + break; + + case IMGIF_PKGTB_IMG_SEGMENT_PKGT: + /* Copy to local buffer */ + dest_ptr = ctxP->pkgt_ptr; + break; + + case IMGIF_PKGTB_IMG_SEGMENT_LOADER: + /* write to local loader */ + dest_ptr = ctxP->loader_ptr; + break; + + case IMGIF_PKGTB_IMG_SEGMENT_ROOTFS: + dest_fh = ctxP->rootfs_fh; + break; + + case IMGIF_PKGTB_IMG_SEGMENT_BOOTFS: + dest_fh = ctxP->bootfs_fh; + break; + + default: + printf("%s: Invalid segment! %d\n", __FUNCTION__, ctxP->current_img_segment_idx); + return -1; + break; + } + + /* Write data to either local memory or to filesystem */ + if( dest_ptr ) + { + imgif_debug("Writing %d bytes to ptr:%p\n", bytes_to_write, + (dest_ptr + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone)); + memcpy(dest_ptr + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone, + datap+pktbuf_segdata_offset, bytes_to_write); + dest_ptr = NULL; + } + else if( dest_fh ) + { +#if IMG_WRITE_FS + imgif_debug("Writing %d bytes to file:%p\n", bytes_to_write, + (dest_fh)); + fwrite(datap+pktbuf_segdata_offset, 1, bytes_to_write, dest_fh); + if( ferror(dest_fh) || feof(dest_fh) ) + { + printf("%s: Error writing segment %d\n", + __FUNCTION__, + ctxP->current_img_segment_idx); + return -1; + } + dest_fh = NULL; +#endif + } + + /* Do whole image crc on all image data including skipped bytes */ + if (ctxP->calCrc32Cb != NULL) + { + ctxP->calCrc32Cb(1, &ctxP->crc_image_calc, + (unsigned char*)datap, + bytes_to_write+pktbuf_segdata_offset); + imgif_debug("crc img tally:0x%08x\n", ctxP->crc_image_calc); + } + +#if !PKGTB_USE_SHELL_SHA256 + //FIXME: Add incremental SHA +#endif + + /* Increment bytes done, advance data pointer and adjust remaining bytes */ + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone += bytes_to_write; + pktbuf_num_bytes -= (bytes_to_write + pktbuf_segdata_offset); + datap += (bytes_to_write + pktbuf_segdata_offset); + written_bytes += (bytes_to_write + pktbuf_segdata_offset); + ctxP->total_img_bytesdone += (bytes_to_write + pktbuf_segdata_offset); + pktbuf_segdata_offset = 0; + + imgif_debug("img_bytesdone:%llu, seg_bytes_done:%llu/%llu, written_bytes:%d/%d\n", + ctxP->total_img_bytesdone, + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone, + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].size, + written_bytes, + pktbuf_num_bytes+written_bytes); + + /* Move to next segment if current segment is done */ + if( ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].bytesdone == + ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].size ) + { + imgif_debug("Segment %d completed\n", ctxP->current_img_segment_idx); + + /* Handle one completed segment */ + if( handle_segment_completion(ctxP) ) + return -1; + + /* Increment to next valid segment */ + while( ctxP->current_img_segment_idx < ctxP->num_img_segments ) + { + ctxP->current_img_segment_idx++; + imgif_debug("Segment change:%d->%d\n", + ctxP->current_img_segment_idx-1, + ctxP->current_img_segment_idx); + + /* Break out if valid segment is detected */ + if( ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].size && + (ctxP->pkgtb_img_segments[ctxP->current_img_segment_idx].type + != IMGIF_PKGTB_IMG_SEGMENT_UNKNOWN )) + break; + } + + } + imgif_debug("\n"); + } + print_imgupdate_progress(ctxP); + return written_bytes; +} + +#if CC_IMGIF_DEBUG +/***************************************************************************** +* FUNCTION: dump_ctx +* PURPOSE: dump all pkgtb img write related parameters. +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* RETURNS: +* NOTES: +* None. +*****************************************************************************/ +static void dump_ctx(imgif_ctx_t *ctxP) +{ + int i = 0; + imgif_debug("------------------------imgif_pkgtb ctx------------------------------\n"); + for( i=0; ipkgtb_img_segments[i].data_offset, + ctxP->pkgtb_img_segments[i].size, + ctxP->pkgtb_img_segments[i].bytesdone); + } + imgif_debug("crc_image_calc 0x%08x crc_image_exp 0x%08x\n", + ctxP->crc_image_calc, ctxP->imgInfoExt.crc); + imgif_debug("boot_partition : %d\n", ctxP->booted_img_idx); + imgif_debug("update_partition : %d\n", ctxP->update_img_idx); + imgif_debug("--------------------------------------------------------------------\n"); +} +#endif + +/***************************************************************************** +* FUNCTION: finalize_pkgtb_img_write +* PURPOSE: Finalize all write operations. +* PARAMETERS: +* ctxP (IN) - IMGIF context pointer. +* abortFlag (IN) - flag indicating early abort. +* RETURNS: +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +static int finalize_pkgtb_img_write(imgif_ctx_t *ctxP, unsigned char abortFlag) +{ + int ret = -1; + int valid_flag; + int seq_num = 0; + int other_image; + imgif_flash_info_t flashInfo; +#if PKGTB_FORKED_WRITES + int child_ret = 0; + pid_t child_pid = 0; + int write_fails = 0; + + /* Make sure that the other forked flash writes have completed successfully */ + while(forked_flash_writes) + { + child_pid = wait(&child_ret); + child_ret = WEXITSTATUS(child_ret); + printf("%s: Child with PID %ld exited with status 0x%x.\n",__FUNCTION__, (long)child_pid, child_ret); + forked_flash_writes--; + if( child_ret ) + write_fails++; + } + if(write_fails) + { + printf("%s: Error! Segment flashing failed.\n",__FUNCTION__); + goto cleanup; + } +#endif + + if( abortFlag ) + goto cleanup; + + /* Check if the whole image CRC matched */ + if((ctxP->calCrc32Cb != NULL) && (ctxP->imgInfoExt.bitmask & IMG_INFO_BITMASK_CRC)) + { + + ctxP->calCrc32Cb(2, &ctxP->crc_image_calc, NULL, 0); + if( ctxP->crc_image_calc != ctxP->imgInfoExt.crc ) + { + printf("%s: Whole Image CRC check failed! expected:0x%08x, calculated:0x%08x\n", + __FUNCTION__, + ctxP->imgInfoExt.crc, + ctxP->crc_image_calc); + goto cleanup; + } + } + + /* Check if size matched */ + if ((ctxP->imgInfoExt.bitmask & IMG_INFO_BITMASK_SIZE) && (ctxP->imgInfoExt.size != ctxP->total_img_bytesdone)) + { + printf("Unmatched file size values, ext=0x%08x, cal=0x%llx", + ctxP->imgInfoExt.size, (unsigned long long)ctxP->total_img_bytesdone); + goto cleanup; + } + +#if IMG_WRITE_FS + + /* Verify we actually wrote out correct number of img segments. */ + if (ctxP->num_img_segments != ctxP->num_img_segments_complete) + { + printf("%s: ERROR: img segments in header=%d complete=%d\n", + __FUNCTION__, + ctxP->num_img_segments, ctxP->num_img_segments_complete); + goto cleanup; + } + + /* Write loader to partition */ + if( ctxP->loader_seg_index != PKGTB_SEG_IDX_INVALID && + ctxP->pkgtb_img_segments[ctxP->loader_seg_index].bytesdone ) + { + if(finalize_loader(ctxP)) + { + printf("%s: Error writing loader segment %d\n", + __FUNCTION__, + ctxP->loader_seg_index); + goto cleanup; + } + } + + /* Set image as valid */ + //FIXME SPI NOR only support single image + imgif_pkgtb_get_flash_info(&flashInfo); +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + if ( flashInfo.flashType != FLASH_INFO_FLAG_NOR ) + { + if (ctxP->force_upd_img_idx) { + int other_seq_num = -1, other_valid_flag = 0; + valid_flag = 1; + setImgValidStatus(ctxP->update_img_idx, &valid_flag); + getImgSeqNum (ctxP->booted_img_idx, &seq_num); + + other_image = ctxP->update_img_idx == 1 ? 2 : 1; + getImgValidStatus(other_image, &other_valid_flag); + if (other_valid_flag) + { + getImgSeqNum (other_image, &other_seq_num); + } + seq_num = (seq_num > other_seq_num)?seq_num:other_seq_num; + seq_num = (seq_num + 1 ) % 1000; + if (seq_num < other_seq_num) { + seq_num = 1; + other_seq_num = 0; + setImgSeqNum(ctxP->update_img_idx, seq_num); + setImgSeqNum(other_image, other_seq_num); + } else { + setImgSeqNum(ctxP->update_img_idx, seq_num); + } + printf("%s: Single Image: seq_num %d %d valid %d %d update_img_idx %d\n", + __FUNCTION__, seq_num, other_seq_num, + valid_flag, other_valid_flag, ctxP->update_img_idx); + if (setBootImageState(BOOT_SET_NEW_IMAGE) != 0) { + fprintf(stderr,"%s setBootImageState(BOOT_SET_NEW_IMAGE) failed\n", __FUNCTION__); + } + } else { + valid_flag = 1; + fprintf(stderr, "%s:%d calling setImgValidStatus\n", __FUNCTION__, __LINE__); + setImgValidStatus(ctxP->update_img_idx, &valid_flag); + other_image = ctxP->update_img_idx == 1 ? 2 : 1; + getImgValidStatus(other_image, &valid_flag); + if (valid_flag) + { + getImgSeqNum (other_image, &seq_num); + seq_num = (seq_num + 1) % 1000; + } + setImgSeqNum( ctxP->update_img_idx, seq_num); + } + + } +#else + if ( flashInfo.flashType != FLASH_INFO_FLAG_NOR ) + { + valid_flag = 1; + fprintf(stderr, "%s:%d calling setImgValidStatus\n", __FUNCTION__, __LINE__); + setImgValidStatus(ctxP->update_img_idx, &valid_flag); + other_image = ctxP->update_img_idx == 1 ? 2 : 1; + getImgValidStatus(other_image, &valid_flag); + if (valid_flag) + { + getImgSeqNum (other_image, &seq_num); + seq_num = (seq_num + 1) % 1000; + } + setImgSeqNum( ctxP->update_img_idx, seq_num); + } +#endif +#endif + ret = 0; + +cleanup: + /* deinitialize context */ + deinit_ctx(ctxP); + + return ret; +} + +/***************************************************************************** +* FUNCTION: imgif_pkgtb_open +* PURPOSE: Initialize IMGIF context. +* PARAMETERS: +* fmtParserCb (IN) Image parser callback function. + calCrc32Cb (IN) Application-specific CRC algorithm callback function. +* RETURNS: +* Pointer to the IMGIF context - successful operation. +* NULL - failed operation, for example, another software upgrade already +* in progress. +* NOTES: +* None. +*****************************************************************************/ +IMGIF_HANDLE imgif_pkgtb_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb) +{ + imgif_ctx_t *ctxP; + ctxP = getCtx(); + memset(ctxP, 0, sizeof(imgif_ctx_t)); + + /* Assign callbacks */ + ctxP->fmtParserCb = fmtParserCb; + ctxP->calCrc32Cb = calCrc32Cb; + + /* Initialize context */ + if( init_ctx(ctxP) == -1 ) + return NULL; + + return((imgif_ctx_t *)ctxP); +} + +/***************************************************************************** +* FUNCTION: imgif_pkgtb_write +* PURPOSE: Write image block to IMGIF. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* dataP (IN) - image block data pointer. +* len (IN) - image block size. +* RETURNS: +* >=0 - number of bytes written. +* -1 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +int imgif_pkgtb_write(IMGIF_HANDLE h, UINT8 *dataP, int len) +{ + imgif_ctx_t *ctxP = getCtxByHandle(h); + return(write_bytes_to_pkgtb_device( ctxP, (char*)dataP, len)); +} + +/***************************************************************************** +* FUNCTION: imgif_pkgtb_close +* PURPOSE: Close IMGIF context. +* PARAMETERS: +* h (IN) - IMGIF context pointer. +* abortFlag (IN) - TRUE: user aborts the operation. +* RETURNS: +* 0 - successful operation. +* -1 - failed operation. +* NOTES: +* User may stop an upgrade at any time, when there is an operator, +* command, protocol failure, or unmatched image size and/or CRC values +* between IMGIF and user. +*****************************************************************************/ +int imgif_pkgtb_close(IMGIF_HANDLE h, UBOOL8 abortFlag) +{ + imgif_ctx_t *ctxP = getCtxByHandle(h); + DUMPIMGIFCTX(ctxP); + return(finalize_pkgtb_img_write(ctxP, abortFlag)); +} + +/***************************************************************************** +* FUNCTION: imgif_pkgtb_set_image_info +* PURPOSE: Set image info obtained externally. +* PARAMETERS: + h (IN) - IMGIF context pointer. + imgInfoExtP (OUT) - image info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. However, it is typically +* invoked at the end of the upgrade, when user has received the whole +* image, and has obtained the image integrity information. +*****************************************************************************/ +int imgif_pkgtb_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoExtP) +{ + imgif_ctx_t *ctxP = getCtxByHandle(h); + + if ((ctxP != NULL) && (imgInfoExtP != NULL)) + { +#if defined(CUSTOM_NAND_SINGLE_IMAGE) || defined(RTCONFIG_SINGLEIMG_B) + ctxP->imgInfoExt.bitmask = (imgInfoExtP->bitmask != 0)? + imgInfoExtP->bitmask: ctxP->imgInfoExt.bitmask; + ctxP->imgInfoExt.size = (imgInfoExtP->size != 0)? + imgInfoExtP->size: ctxP->imgInfoExt.size; + ctxP->imgInfoExt.crc = (imgInfoExtP->crc != 0)? + imgInfoExtP->crc: ctxP->imgInfoExt.crc; + + ctxP->force_upd_img_idx = (imgInfoExtP->force_upd_img_idx != 0)? + imgInfoExtP->force_upd_img_idx: ctxP->imgInfoExt.force_upd_img_idx; + + imgif_debug("imgif_pkgtb_set_image_info bitmask %x %x !!", + ctxP->imgInfoExt.bitmask, imgInfoExtP->bitmask); + imgif_debug("size %x %x ", ctxP->imgInfoExt.size, imgInfoExtP->size); + imgif_debug("crc %x %x ", ctxP->imgInfoExt.crc, imgInfoExtP->crc); + imgif_debug("force_upd_img_idx %x %x !!\n", + ctxP->imgInfoExt.force_upd_img_idx, imgInfoExtP->force_upd_img_idx); + + if (ctxP->force_upd_img_idx) { + ctxP->update_img_idx = ctxP->force_upd_img_idx; + imgif_debug("Override upd img index to %d !!\n", ctxP->update_img_idx); + } +#else + ctxP->imgInfoExt.bitmask = imgInfoExtP->bitmask; + ctxP->imgInfoExt.size = imgInfoExtP->size; + ctxP->imgInfoExt.crc = imgInfoExtP->crc; +#endif + return 0; + } + + return -1; +} + +/***************************************************************************** +* FUNCTION: imgif_pkgtb_get_flash_info +* PURPOSE: Obtain flash info. +* PARAMETERS: + h (IN) - IMGIF context pointer. + flashInfoP (OUT) - flash info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time. +*****************************************************************************/ +int imgif_pkgtb_get_flash_info(imgif_flash_info_t *flashInfoP) +{ + int ret = -1; + mtd_info_t *mtdP; + int mtdFd; + unsigned int flags; + UINT32 flashSize=0; + + imgif_debug("Enter, info=%p.", flashInfoP); + ret = getFlashInfo(&flags); + + if( ret == 0 ) + { + flashInfoP->flashType = flags; + if( flags == FLASH_INFO_FLAG_NAND ) + { + mtdP = get_mtd_device_handle(PKGTB_MTD_IMG_DEV_NAME, &mtdFd, 0); + if (mtdP == NULL) + { + imgif_error("get_mtd_device_handle(%s) failed", PKGTB_MTD_IMG_DEV_NAME); + return -1; + } + else + { + flashInfoP->eraseSize = mtdP->erasesize; + flashInfoP->flashSize = mtdP->size; + free(mtdP); + close(mtdFd); + } + } + else if ( flags == FLASH_INFO_FLAG_EMMC ) + { + flashInfoP->eraseSize = 0; + + if(isLegacyFlashLayout()) + { + ret = devCtl_boardIoctl(BOARD_IOCTL_FLASH_READ, + FLASH_SIZE, + 0, 0, 0, &flashSize); + if( ret == 0 ) + flashInfoP->flashSize = flashSize; + } + else + { +#ifndef DESKTOP_LINUX + flashInfoP->flashSize = emmcGetAvailLoaderSpace() + 2 * emmcGetAvailImgSpace(1); +#else + flashInfoP->flashSize = 0x1000000; +#endif + } + } + else if ( flags == FLASH_INFO_FLAG_NOR ) + { + mtdP = get_mtd_device_handle(SPI_NOR_FLASH_NAME, &mtdFd, 0); + if (mtdP == NULL) + { + imgif_error("get_mtd_device_handle(%s) failed", SPI_NOR_FLASH_NAME); + return -1; + } + else + { + flashInfoP->eraseSize = mtdP->erasesize; + flashInfoP->flashSize = mtdP->size; + free(mtdP); + close(mtdFd); + } + } + else + { + imgif_error("Unsupported Flash Device!!\n"); + return -1; + } + } + return(0); +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_pkgtb.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_pkgtb.h new file mode 100644 index 00000000000..42ffa4002e1 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgif_pkgtb.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * + * Copyright (c) 2015 Broadcom Corporation + * All Rights Reserved + * + * <:label-BRCM:2015:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * + ****************************************************************************/ + +#ifndef BCM_IMGIF_PKGTB_H +#define BCM_IMGIF_PKGTB_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include "bcm_imgif.h" + +/* ---- Constants and Types ----------------------------------------------- */ +/* ---- Variable Externs -------------------------------------------------- */ +/* ---- Function Prototypes ----------------------------------------------- */ + +IMGIF_HANDLE imgif_pkgtb_open(IMG_FORMAT_PARSER_CB fmtParserCb, + CAL_CRC32_CB calCrc32Cb); +int imgif_pkgtb_write(IMGIF_HANDLE h, UINT8 *dataP, int len); +int imgif_pkgtb_close(IMGIF_HANDLE h, UBOOL8 abortFlag); +int imgif_pkgtb_set_image_info(IMGIF_HANDLE h, imgif_img_info_t *imgInfoP); +int imgif_pkgtb_get_flash_info(imgif_flash_info_t *flashInfoP); + +#endif /* CMS_IMGIF_PKGTB_H */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil.c new file mode 100755 index 00000000000..320148317d5 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil.c @@ -0,0 +1,859 @@ +/*********************************************************************** + * <:copyright-BRCM:2016:DUAL/GPL:standard + * + * Copyright (c) 2016 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +/*!\file bcm_imgutil.c + * \brief Broadcom firmware image utils. Most of this file is copied from + * cms_util/image.c This file is the correct place for most + * Broadcom image utils, since the image functions applies to + * non-CMS builds as well. Going forward, make fixes and enhancements + * in this file and redirect calls from image.c to this file. + * + */ + +#include +#include +#include +#include +#ifdef DESKTOP_LINUX +#include +#endif /* DESKTOP_LINUX */ + +#include "bcmTag.h" +#include "board.h" +#include "bcm_boarddriverctl.h" + +#include "genutil_crc.h" +#include "bcm_flashutil.h" +#include "bcm_flashutil_nand.h" +#include "bcm_flashutil_emmc.h" +#include "bcm_flashutil_nor.h" +#include "bcm_imgutil.h" +#include "libfdt.h" + +/* #define CC_IMGUTIL_DEBUG 1 */ +#define cmsLog_error(fmt, arg...) \ + printf("ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#if defined(CC_IMGUTIL_DEBUG) +#define cmsLog_debug(fmt, arg...) \ + printf("%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#else + #define cmsLog_debug(fmt, arg...) +#endif /* CC_IMGUTIL_DEBUG */ +#if defined(CC_IMGUTIL_NOTICE) +#define cmsLog_notice(fmt, arg...) \ + printf("%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#else + #define cmsLog_notice(fmt, arg...) +#endif /* CC_IMGUTIL_NOTICE */ + + +static UBOOL8 matchChipId(const char *strTagChipId, const char *signature2); +CmsRet bcmImg_verifyBroadcomFileTag(FILE_TAG *pTag, UBOOL8 fullImageB, int imageLen); +void dumpBcmFileTag(FILE_TAG *tagP); + + +UBOOL8 bcmImg_MatchChipId( const char *strTagChipId ) +{ + return(matchChipId(strTagChipId, NULL)); +} + +/** + * @return TRUE if the modem's chip id matches that of the image. + */ +static UBOOL8 matchChipId(const char *strTagChipId, const char *signature2 __attribute__((unused))) +{ + UINT32 tagChipId = 0; + UINT32 chipId; + UBOOL8 match; + + /* this is the image's chip id */ + tagChipId = (UINT32) strtol(strTagChipId, NULL, 16); + + /* get the system's chip id */ + devCtl_getChipId(&chipId); + if (tagChipId == chipId) + { + match = TRUE; + } + else if (tagChipId == CHIP_FAMILY_ID_HEX) + { + match = TRUE; + } + else + { + cmsLog_error("Chip Id error. Image Chip Id = %04x, Board Chip Id = %04x.", tagChipId, chipId); + match = FALSE; +#ifdef DESKTOP_LINUX + match = TRUE; /* For debugging. */ +#endif + } + + return match; +} + +// verify the tag of the image +CmsRet bcmImg_verifyBroadcomFileTag(FILE_TAG *pTag, UBOOL8 fullImageB, int imageLen) +{ + UINT32 crc; + int totalImageSize; + int tagVer, curVer; + UINT32 tokenCrc, imageCrc, *pTokenCrc, *pImageCrc; + + + cmsLog_debug("start of pTag=%p tagversion %02x %02x %02x %02x", pTag, + pTag->tagVersion[0], + pTag->tagVersion[1], + pTag->tagVersion[2], + pTag->tagVersion[3]); + + pTokenCrc = (UINT32 *)pTag->tagValidationToken; + tokenCrc = *pTokenCrc; + pImageCrc = (UINT32 *)pTag->imageValidationToken; + imageCrc = *pImageCrc; +#ifdef DESKTOP_LINUX + /* assume desktop is running on little endien intel, but the CRC has been + * written for big endien mips, so swap before compare. + * FIXME! this part of code might not work with Little-endian target system. + */ + tokenCrc = htonl(tokenCrc); + imageCrc = htonl(imageCrc); +#endif + + // check tag validate token first + crc = CRC_INITIAL_VALUE; + crc = genUtl_getCrc32((UINT8 *) pTag, (UINT32)TAG_LEN-TOKEN_LEN, crc); + if (crc != tokenCrc) + { + /* this function is called even when we are not sure the image is + * a broadcom image. So if crc fails, it is not a big deal. It just + * means this is not a broadcom image. + */ + cmsLog_debug("token crc failed, this is not a valid broadcom image"); + cmsLog_debug("calculated crc=0x%x tokenCrc=0x%x", crc, tokenCrc); + return CMSRET_INVALID_IMAGE; + } + cmsLog_debug("header CRC is OK."); + + tagVer = atoi((char *) pTag->tagVersion); + curVer = atoi(BCM_TAG_VER); + + if (tagVer != curVer) + { + cmsLog_error("Firmware tag version [%d] is not compatible with the current Tag version [%d]", tagVer, curVer); + return CMSRET_INVALID_IMAGE; + } + + cmsLog_debug("tarVer=%d, curVar=%d", tagVer, curVer); + + if (!matchChipId((char *) pTag->chipId, (char *) pTag->signiture_2)) + { + cmsLog_error("chipid check failed"); + return CMSRET_INVALID_IMAGE; + } + + cmsLog_debug("chipid is OK"); + + if (fullImageB == FALSE) + { + cmsLog_debug("Good broadcom image header"); + return CMSRET_SUCCESS; + } + + // check imageCrc + totalImageSize = atoi((char *) pTag->totalImageLen); + cmsLog_debug("totalImageLen=%d, imageLen=%d, TAG_LEN=%d\n", totalImageSize, imageLen, TAG_LEN); + + if (totalImageSize > (imageLen -TAG_LEN)) + { + cmsLog_error("invalid size\n"); + return CMSRET_INVALID_IMAGE; + } + crc = CRC_INITIAL_VALUE; + crc = genUtl_getCrc32(((UINT8 *)pTag + TAG_LEN), (UINT32) totalImageSize, crc); + if (crc != imageCrc) + { + /* + * This should not happen. We already passed the crc check on the header, + * so we should pass the crc check on the image. If this fails, something + * is wrong. + */ + cmsLog_error("image crc failed after broadcom header crc succeeded"); + cmsLog_error("calculated crc=0x%x imageCrc=0x%x totalImageSize=%d", crc, imageCrc, totalImageSize); + return CMSRET_INVALID_IMAGE; + } + cmsLog_debug("image crc is OK"); + + cmsLog_debug("Good broadcom image"); + + return CMSRET_SUCCESS; +} + + +// depending on the image type, do the brcm image or whole flash image +CmsRet bcmImg_flashImage(char *imagePtr, UINT32 imageLen, CmsImageFormat format, UINT32 opts, int * noReboot) +{ + FILE_TAG *pTag = (FILE_TAG *) imagePtr; + int cfeSize, rootfsSize, kernelSize; + unsigned long cfeAddr, rootfsAddr, kernelAddr; + UINT32 flags=0; + CmsRet ret; + + if( opts & CMS_IMAGE_WR_OPT_PART1 ) + { + *noReboot = (opts & CMS_IMAGE_WR_OPT_NO_REBOOT) ? FLASH_PART1_NO_REBOOT : FLASH_PART1_REBOOT; + } + else if( opts & CMS_IMAGE_WR_OPT_PART2 ) + { + *noReboot = (opts & CMS_IMAGE_WR_OPT_NO_REBOOT) ? FLASH_PART2_NO_REBOOT : FLASH_PART2_REBOOT; + } + else + { + *noReboot = (opts & CMS_IMAGE_WR_OPT_NO_REBOOT) ? FLASH_PARTDEFAULT_NO_REBOOT : FLASH_PARTDEFAULT_REBOOT; + } + + cmsLog_debug("format=%d noReboot=0x%x", format, *noReboot); + + if (format != CMS_IMAGE_FORMAT_FLASH && format != CMS_IMAGE_FORMAT_BROADCOM) + { + cmsLog_error("invalid image format %d", format); + return CMSRET_INVALID_IMAGE; + } + + if (format == CMS_IMAGE_FORMAT_FLASH) + { + cmsLog_notice("Flash whole image..."); + // Pass zero for the base address of whole image flash. It will be filled by kernel code + // was sysFlashImageSet + if ((ret = getFlashInfo(&flags)) == CMSRET_SUCCESS) + { + if(flags & FLASH_INFO_FLAG_NOR) + { // NOR flash device + ret = devCtl_boardIoctl(BOARD_IOCTL_FLASH_WRITE, + BCM_IMAGE_WHOLE, + imagePtr, + imageLen-TOKEN_LEN, + *noReboot, 0); + } + else + { // NAND flash device + ret = writeImageToNand( (unsigned char *)imagePtr, imageLen - TOKEN_LEN ); + } + } + + if (ret != CMSRET_SUCCESS) + { + cmsLog_error("Failed to flash whole image"); + return CMSRET_IMAGE_FLASH_FAILED; + } + else + { + return CMSRET_SUCCESS; + } + } + + /* this must be a broadcom format image */ + // check imageCrc + cfeSize = rootfsSize = kernelSize = 0; + + // check cfe's existence + cfeAddr = (unsigned long) strtoul((char *) pTag->cfeAddress, NULL, 10); + cfeSize = atoi((char *) pTag->cfeLen); + // check kernel existence + kernelAddr = (unsigned long) strtoul((char *) pTag->kernelAddress, NULL, 10); + kernelSize = atoi((char *) pTag->kernelLen); + // check root filesystem existence + rootfsAddr = (unsigned long) strtoul((char *) pTag->rootfsAddress, NULL, 10); + rootfsSize = atoi((char *) pTag->rootfsLen); + cmsLog_debug("cfeSize=%d kernelSize=%d rootfsSize=%d", cfeSize, kernelSize, rootfsSize); + + if (cfeAddr) + { + printf("Flashing CFE...\n"); + + ret = devCtl_boardIoctl(BOARD_IOCTL_FLASH_WRITE, + BCM_IMAGE_CFE, + imagePtr+TAG_LEN, + cfeSize, + (int) cfeAddr, 0); + if (ret != CMSRET_SUCCESS) + { + cmsLog_error("Failed to flash CFE"); + return CMSRET_IMAGE_FLASH_FAILED; + } + } + + if (rootfsAddr && kernelAddr) + { + char *tagFs = imagePtr; + + // tag is alway at the sector start of fs + if (cfeAddr) + { + tagFs = imagePtr + cfeSize; // will trash cfe memory, but cfe is already flashed + memcpy(tagFs, imagePtr, TAG_LEN); + } + + printf("Flashing root file system and kernel...\n"); + /* only the buf pointer and length is needed, the offset parameter + * was present in the legacy code, but is not used. */ + ret = devCtl_boardIoctl(BOARD_IOCTL_FLASH_WRITE, + BCM_IMAGE_FS, + tagFs, + TAG_LEN+rootfsSize+kernelSize, + *noReboot, 0); + if (ret != CMSRET_SUCCESS) + { + cmsLog_error("Failed to flash root file system and kernel"); + return CMSRET_IMAGE_FLASH_FAILED; + } + } + + cmsLog_notice("Image flash done."); + + return CMSRET_SUCCESS; +} + + +CmsRet get_mtd_device_size(const char * partition, unsigned int * size) +{ + FILE *fp; + char sze[MAX_MTD_NAME_SIZE] = {0}; + char line[MAX_MTD_NAME_SIZE*2] = {0}; + char name[MAX_MTD_NAME_SIZE] = {0}; + char compare[MAX_MTD_NAME_SIZE] = {0}; + + if ( (fp = fopen("/proc/mtd","r")) == 0) + { + printf("ERROR in %s!!! Could not open /proc/mtd\n", __FUNCTION__); + + return(CMSRET_OPEN_FILE_ERROR); + } + + snprintf(compare, sizeof(compare), "%s%s%s", "\"", partition, "\""); + + while(fgets(line, sizeof(line), fp)) + { + sscanf(line, "%*s %s %*s %s", sze, name); + + if(!strcmp(name, compare)) + { + fclose(fp); + + *size = (unsigned int)strtol(sze, NULL, 16); + + return(CMSRET_SUCCESS); + } + } + + fclose(fp); + + printf("%s: MTD partition/device %s not found/opened\n", __FUNCTION__, partition); + return(CMSRET_OBJECT_NOT_FOUND); +} + + +unsigned int bcmImg_getImageFlashSize(void) +{ + UINT32 flashSize=0; + CmsRet ret = CMSRET_OBJECT_NOT_FOUND; + + if(isLegacyFlashLayout()) + { + ret = devCtl_boardIoctl(BOARD_IOCTL_FLASH_READ, + FLASH_SIZE, + 0, 0, 0, &flashSize); + } + else + { + unsigned int gFlashInfo = 0; + + getFlashInfo(&gFlashInfo); + + if (gFlashInfo == FLASH_INFO_FLAG_NAND) + { + ret = get_mtd_device_size("image", &flashSize); + } + else if (gFlashInfo == FLASH_INFO_FLAG_EMMC) + { +#ifndef DESKTOP_LINUX + flashSize = emmcGetAvailLoaderSpace() + 2 * emmcGetAvailImgSpace(1); +#else + flashSize = 0x1000000; +#endif + ret = CMSRET_SUCCESS; + } + else if (gFlashInfo == FLASH_INFO_FLAG_NOR) + ret = get_mtd_device_size(SPI_NOR_FLASH_NAME, &flashSize); + } + + if (ret != CMSRET_SUCCESS) + { + cmsLog_error("Could not get flash size, return 0"); + flashSize = 0; + } + + return flashSize; +} + + +unsigned int bcmImg_getBroadcomImageTagSize(void) +{ + return TOKEN_LEN; +} + + +unsigned int bcmImg_getConfigFlashSize(void) +{ + UINT32 realSize; + + realSize = bcmImg_getRealConfigFlashSize(); + +#ifdef COMPRESSED_CONFIG_FILE + /* + * A multiplier of 2 is now too small for some of the big voice and WLAN configs, + * so allow for the possibility of 4x compression ratio. In a recent test on the + * 6368 with wireless enabled, I got a compression ratio of 3.5. + * The real test comes in management.c: after we do the + * compression, writeValidatedConfigBuf will verify that the compressed buffer can + * fit into the flash. + * A 4x multiplier should be OK for small memory systems such as the 6338. + * The kernel does not allocate physical pages until they are touched. + * However, allocating an overly large buffer could be rejected immediately by the + * kernel because it does not know we don't actually plan to use the entire buffer. + * So if this is a problem on the 6338, we could improve this algorithm to + * use a smaller factor on low memory systems. + */ + realSize = realSize * 4; +#endif + + return realSize; +} + + +unsigned int bcmImg_getRealConfigFlashSize(void) +{ + CmsRet ret; + UINT32 size=0; + UINT32 flags=0; + + if ((ret = getFlashInfo(&flags)) == CMSRET_SUCCESS) + { + if(flags & FLASH_INFO_FLAG_NOR) + { +#ifndef DESKTOP_LINUX + if( norIsNewFlashLayout()) + size=128*1024; + else +#endif + { + ret = devCtl_boardIoctl(BOARD_IOCTL_GET_PSI_SIZE, 0, NULL, 0, 0, (void *)&size); + if (ret != CMSRET_SUCCESS) + { + cmsLog_error("boardIoctl to get config flash size failed."); + size = 0; + } + } + } + else + { + /* + * If we are using NAND, config file is stored in the /data partition, + * so config file size is only limited by the size of the /data + * partition. For now, implement a quick solution and hardcode the + * NAND config file size to 128KB (so far, nothing has hit this limit). + * In the future, could improve this solution by: + * - checking against size of /data partition + * - if we have 1 copy or 2 (for backup config file). + * whether we are doing a distributed MDM config (done by BDK) + * - reserve the space on the FS so there is no chance FS is too + * full to accept the config file. + */ + size=128*1024; // 128KB + } + } + else + { + cmsLog_error("could not determine NAND or NOR"); + } + + cmsLog_debug("returning size=%d", size); + + return size; +} + + +unsigned char bcmImg_willFitInFlash(unsigned int imageSize) +{ + UINT32 flashSize; + +#ifdef DESKTOP_LINUX + flashSize = 2 * (imageSize + CMS_IMAGE_OVERHEAD); +#else + flashSize = bcmImg_getImageFlashSize(); + + cmsLog_debug("flash size is %u bytes, imageSize=%u bytes", flashSize, imageSize); +#endif /* DESKTOP_LINUX */ + + return (flashSize > (imageSize + CMS_IMAGE_OVERHEAD)); +} + + +unsigned char bcmImg_isBackupConfigFlashAvailable(void) +{ + static UBOOL8 firstTime=TRUE; + static UBOOL8 avail=FALSE; + CmsRet ret; + + if (firstTime) + { + UINT32 size=0; + UINT32 flags=0; + + if ((ret = getFlashInfo(&flags)) == CMSRET_SUCCESS) + { + if(flags & FLASH_INFO_FLAG_NOR) + { +#ifndef DESKTOP_LINUX + if( norIsNewFlashLayout() ) + avail = TRUE; + else +#endif + { + ret = devCtl_boardIoctl(BOARD_IOCTL_GET_BACKUP_PSI_SIZE, 0, NULL, + 0, 0, (void *)&size); + if (ret == CMSRET_SUCCESS) + { + avail = TRUE; + } + } + } + else + { + // Backup PSI file is always available in NAND + avail = TRUE; + } + } + else + { + cmsLog_error("could not determine NAND or NOR"); + } + + firstTime = FALSE; + } + + return avail; +} + + +unsigned char bcmImg_isConfigFileLikely(const char *buf) +{ + const char *header = " sizeof(struct fdt_header)) && (fdt_check_header(imageBuf) == 0)) + { + /* Found a valid Broadcom defined TAG record at the beginning of the image */ + cmsLog_debug("Broadcom pktb format verified."); + + //FIXME: Cannot detemine total size of image at this point since we may not + //have the entire dtb in memory. Will do that later + result = CMS_IMAGE_FORMAT_BROADCOM; + } + else if ((imageLen > sizeof(FILE_TAG)) && (bcmImg_verifyBroadcomFileTag((FILE_TAG *) imageBuf, 1, imageLen) == CMSRET_SUCCESS)) + { + UINT32 maxLen; + + /* Found a valid Broadcom defined TAG record at the beginning of the image */ + cmsLog_debug("Broadcom format verified."); + maxLen = bcmImg_getImageFlashSize() + bcmImg_getBroadcomImageTagSize(); + if (imageLen > maxLen) + { + cmsLog_error("broadcom image is too large for flash, got %u, max %u", imageLen, maxLen); + } + else + { + result = CMS_IMAGE_FORMAT_BROADCOM; + } + } + else + { + /* if It is not a Broadcom flash format file. Now check if it is a + * flash image format file. A flash image format file must have a + * CRC at the end of the image. + */ + UINT32 crc = CRC_INITIAL_VALUE; + UINT32 imageCrc; + UINT8 *crcPtr; + + if (imageLen > TOKEN_LEN) + { + crcPtr = (UINT8 *) (imageBuf + (imageLen - TOKEN_LEN)); + /* + * CRC may not be word aligned, so extract the bytes out one-by-one. + * Whole image CRC is calculated, then htonl, then written out using + * fwrite (see addvtoken.c in hostTools). Because of the way we are + * extracting the CRC here, we don't have to swap for endieness when + * doing compares on desktop Linux and modem (?). + */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + imageCrc = crcPtr[0] | (crcPtr[1] << 8) | (crcPtr[2] << 16) | (crcPtr[3] << 24); +#else + imageCrc = (crcPtr[0] << 24) | (crcPtr[1] << 16) | (crcPtr[2] << 8) | crcPtr[3]; +#endif + + crc = genUtl_getCrc32((unsigned char *) imageBuf, imageLen - TOKEN_LEN, crc); +#ifndef DESKTOP_LINUX + if (crc == imageCrc) +#else + if ((crc == imageCrc) || crc == htonl(imageCrc)) +#endif + { + UINT32 maxLen; + + cmsLog_debug("Whole flash image format [%d bytes] verified.", imageLen); + maxLen = bcmImg_getImageFlashSize(); + if (imageLen > maxLen) + { + cmsLog_error("whole image is too large for flash, got %u, max %u", imageLen, maxLen); + } + else + { + result = CMS_IMAGE_FORMAT_FLASH; + } + } + else + { +#if defined(EPON_SDK_BUILD) + cmsLog_debug("Could not determine image format [%d bytes]", imageLen); +#else + cmsLog_error("Could not determine image format [%d bytes]", imageLen); +#endif + cmsLog_debug("calculated crc=0x%x image crc=0x%x", crc, imageCrc); + } + } + } + + cmsLog_debug("returning image format %d", result); + + return result; +} + + +UBOOL8 bcmImg_isBcmTaggedImage(const char *imageBuf, UINT32 *imageSize) +{ + FILE_TAG *pTag = (FILE_TAG *)imageBuf; + UINT32 crc; + UINT32 tokenCrc, *pTokenCrc; + UBOOL8 isBcmImg = FALSE; + + pTokenCrc = (UINT32 *)pTag->tagValidationToken; + tokenCrc = *pTokenCrc; +#ifdef DESKTOP_LINUX + /* assume desktop is running on little endien intel, but the CRC has been + * written for big endien mips, so swap before compare. + * FIXME! this part of code might not work with Little-endian target system. + */ + tokenCrc = htonl(tokenCrc); +#endif + + /* check tag validate token to see if it is a valid bcmTag */ + crc = CRC_INITIAL_VALUE; + crc = genUtl_getCrc32((UINT8 *) pTag, (UINT32)TAG_LEN-TOKEN_LEN, crc); + if (crc == tokenCrc) + { + isBcmImg = TRUE; + *imageSize = (UINT32) atoi((char *)pTag->totalImageLen) + TAG_LEN; + cmsLog_debug("It's a broadcom tagged image with length %d", *imageSize ); + } + else + { + cmsLog_debug("token crc failed, this is not a valid broadcom image"); + } + + return isBcmImg; + +} + +CmsImageFormat bcmImg_parseImgHdr(UINT8 *bufP, UINT32 bufLen) +{ + CmsImageFormat result = CMS_IMAGE_FORMAT_INVALID; + + if (bufP == NULL) + { + cmsLog_debug("NULL bufP pointer."); + result = CMS_IMAGE_FORMAT_INVALID; + } + else if ((bufLen > CMS_CONFIG_FILE_DETECTION_LENGTH) && + bcmImg_isConfigFileLikely((char*)bufP)) + { + cmsLog_debug("Detected possible CMS XML config file format"); + result = CMS_IMAGE_FORMAT_XML_CFG; + } +#ifdef SUPPORT_MODSW_LINUXPFP + else if (cmsImg_isModSwLinuxPfp((UINT8*)bufP, bufLen)) + { + cmsLog_debug("Detected Modular Software Linux PFP format."); + result = CMS_IMAGE_FORMAT_MODSW_LINUXPFP; + } +#endif + else if ((bufLen > sizeof(FILE_TAG)) && + (bcmImg_verifyBroadcomFileTag((FILE_TAG*)bufP, 0, bufLen) == CMSRET_SUCCESS)) + { + cmsLog_debug("Detected Broadcom image format."); + result = CMS_IMAGE_FORMAT_BROADCOM; + } + + return result; +} + +void dumpBcmFileTag(FILE_TAG *tagP) +{ + printf("--------------------------------------------------------------\n"); + printf("Broadcom image tag:\n"); + printf("\ttagVersion: %02x %02x %02x %02x\n", + tagP->tagVersion[0], tagP->tagVersion[1], + tagP->tagVersion[2], tagP->tagVersion[3]); + printf("\tendian: %s\n", tagP->bigEndian); + printf("\ttotalImageLen: %s\n", tagP->totalImageLen); + printf("\tcfeAddress: %s\n", tagP->cfeAddress); + printf("\tcfeLen: %s\n", tagP->cfeLen); + printf("\trootfsAddress: %s\n", tagP->rootfsAddress); + printf("\trootfsLen: %s\n", tagP->rootfsLen); + printf("\tkernelAddress: %s\n", tagP->kernelAddress); + printf("\tkernelLen: %s\n", tagP->kernelLen); + printf("\timageSequence: %s\n", tagP->imageSequence); + printf("\timageVersion: %s\n", tagP->imageVersion); + printf("--------------------------------------------------------------\n"); +} + +/* + * IMGUTIL_TODO: the following logic is replicated in a few places. + * To consolidate. + * ./private/apps/tr69c/main/informer.c: allocSize -= 64 * 1024; + * ./gpl/apps/ftpd/ftpd/commands.c: totalAllocatedSize -= 64 * 1024; + */ + +/* + * If maxBufSize is initialized, try that (with allocSize = maxBufSize) + * and if still failing, try reducing 64K from allocSize and try again as + * long as allocSize > CMS_IMAGE_REQUIRED_LEN. + */ +UINT8* bcmImg_allocImgBuf(UINT32 maxBufSize, UINT32 *allocBufSizeP) +{ + UINT32 allocSize; + UINT8 *bufP = NULL; + + if (maxBufSize > 0) + { + allocSize = maxBufSize; + } + else + { + allocSize = bcmImg_getImageFlashSize() + + bcmImg_getBroadcomImageTagSize(); + } + + cmsLog_debug("bcmImg_allocImgBuf() begin, %d", allocSize); + + if ((bufP = (UINT8*)malloc(allocSize)) == NULL) + { + /* TODO: this logic in commands.c does not seem to be correct. */ + /* if (maxBufSize > 0) */ + { + while (((bufP = (UINT8*)malloc(allocSize)) == NULL) && + (allocSize > CMS_IMAGE_REQUIRED_LEN)) + { + allocSize -= 64 * 1024; + cmsLog_debug("Try allocating %d kb", allocSize/1024); + } + } + + if (bufP == NULL) + { + cmsLog_error("Not enough memory to alloc %u bytes.", allocSize); + *allocBufSizeP = 0; + return NULL; + } + } + + cmsLog_debug("bcmImg_allocImgBuf() end, %d", allocSize); + + *allocBufSizeP = allocSize; + return bufP; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil.h new file mode 100755 index 00000000000..9c87f1a22a6 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * + * Copyright (c) 2016 Broadcom + * All Rights Reserved + * + * <:label-BRCM:2016:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> +****************************************************************************/ + +/* Split from cms_image.h. */ + +#ifndef _BCM_IMGUTIL_H_ +#define _BCM_IMGUTIL_H_ + +/* ---- Include Files ----------------------------------------------------- */ + +#include "os_defs.h" +#include "cms_retcodes.h" // TODO: should use BcmRet not CmsRet +#include "bcm_retcodes.h" +#include "bcm_imgutil_def.h" + + +/* ---- Constants and Types ----------------------------------------------- */ + +#ifndef CMS_IMAGE_REQUIRED_LEN +#define CMS_IMAGE_REQUIRED_LEN (4 * 1024 * 1024) +#endif + +/* Options: write to partition 1/2. */ +#define CMS_IMAGE_WR_OPT_PART1 0x10 +#define CMS_IMAGE_WR_OPT_PART2 0x20 + +/* Options: Do not reboot after writing image to non-active partition. */ +#define CMS_IMAGE_WR_OPT_NO_REBOOT 0x80 + +#define CMS_IMAGE_OVERHEAD 256 +#define CMS_CONFIG_FILE_DETECTION_LENGTH 64 + +typedef enum +{ + IMGUTIL_PROC_OK = 0, + IMGUTIL_PROC_ERR, + IMGUTIL_PROC_INVALID_IMG, + IMGUTIL_PROC_NOT_FOUND, + IMGUTIL_PROC_FOUND, + IMGUTIL_PROC_MORE_DATA /* Need more data. */ +} imgutil_ret_e; + + +/* ---- Variable Externs -------------------------------------------------- */ + +/* ---- Function Prototypes ----------------------------------------------- */ + +UINT8* bcmImg_allocImgBuf(UINT32 maxBufSize, UINT32 *allocBufSizeP); +UINT32 bcmImg_getImageFlashSize(void); +CmsRet bcmImg_flashImage(char *imagePtr, UINT32 imageLen, + CmsImageFormat format, UINT32 opts, int *noReboot); +CmsImageFormat bcmImg_parseImgHdr(UINT8 *bufP, UINT32 bufLen); +void bcmImg_reboot(void); +UBOOL8 bcmImg_willFitInFlash(UINT32 imageSize); +UBOOL8 bcmImg_isBackupConfigFlashAvailable(void); +imgutil_ret_e bcmImg_getImageVersion(char *imagePtr, int imageLen, char *imageName, + int imageNameLen); +CmsRet bcmImg_verifyBroadcomFileTag(FILE_TAG *pTag, UBOOL8 fullImageB, int imageLen); +CmsImageFormat bcmImg_validateImage(const char *imageBuf, UINT32 imageLen); +UBOOL8 bcmImg_isBcmTaggedImage(const char *imageBuf, UINT32 *imageSize); +UINT32 bcmImg_getConfigFlashSize(void); + +imgutil_ret_e bcmImg_ComboImageInit(void); +imgutil_ret_e bcmImg_ComboImageIdentify(const char *imageBuf, UINT32 imageLen); +imgutil_ret_e bcmImg_ComboImageParseHeader(char *imageBuf, UINT32 imageLen, + UINT32 *consumed, UINT32 *image_len, int *parsingState, + Comboimg_header_tag *comboTagP, Comboimg_individual_img_tag *indvTagP, + imgutil_accept_range_ctx_t *ar_ctx); +UBOOL8 bcmImg_ComboImageParsingDone(void); +UBOOL8 bcmImg_IsValidCombo(void); +UBOOL8 bcmImg_MatchChipId( const char *strTagChipId ); + +#endif /*_BCM_IMGUTIL_H_*/ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil_api.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil_api.c new file mode 100755 index 00000000000..450f65f09ea --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/bcm_imgutil_api.c @@ -0,0 +1,1202 @@ +/***************************************************************************** + * <:copyright-BRCM:2016:DUAL/GPL:standard + * + * Copyright (c) 2016 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ****************************************************************************/ + +/***************************************************************************** +* Description: +* +* This file contains the BCM unified software image flashing utility +* (imgutil) library implementation. +* +* This library runs on top of several utilities: devCtl (NOR, BCM image +* flashing), bcm_flashutil (NAND & UBI flashing), and bcm_imgif (NAND +* incremental flashing). It includes the following functions: +* - Provide a unified flash programming interface to application clients. +* The clients do not need to be aware of the image format, and the +* underlying flashing mechanism. +* - Support the following image formats: +* * Raw SPI-NOR, raw NAND, raw pure-UBI, and BCM image format (without +* the bundle image header). +* * Bundled image with image header, where multiple image files are +* concatenated, and only one actually needs to be programmed. +* - Support the whole image upgrade and incremental image upgrade. In +* the NAND flash case, the library provides the option to either flash +* at the end, or flash on-the-fly. + +* Basic design concept: +* - Receive enough data to determine the image type. +* * Bundle image +* * Configuration file. +* * Non-bundle image: BCM image(tag in head), UBI, NOR flash, NAND, UBI. +* A: No bundle image header: +* - NOR flash: buffer the whole image. When done, validate and then +* call devCtl flashing API. +* - NAND flash and incremental flashing disabled: buffer the whole +* image. When done, validate and then call incremental flashing API. +* - BCM image (tag in head): buffer the whole image. When done, validate +* and then call devCtl flashing API. +* - UBI image: buffer the whole image. When done, validate and then call +* bcm_flashutil API (will be replaced by incremental API later). +* - NAND and incremental enabled: call incremental flashing API. +* B: Bundle image header: +* - Image header parsing, find the correct start offset of +* applicable image (criteria: chip ID, optionally board ID), and find +* the other fields in the header (image len, image flags, CRC, version, +* etc.). +* - Discard non-applicable image buffer. +* - After header parsing: same as (A). +* +* Additional notes: +* - It is client's responsibility to set the image state for the next +* reboot, and reboot the system after the upgrade, using devCtl APIs. +* +* Future extensions: +* - Incremental flashing for the pure UBI image. +* - Incremental flashing for the compressed image (decompress on-the-fly). +* - The bundle image may include both software image and configuration +* file? +* +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ + +#include "bcm_flashutil.h" +#include "bcm_imgutil_api.h" +#include "bcmTag.h" +#include "genutil_crc.h" +#include "bcm_imgutil.h" +#include "bcm_imgif.h" +#include "bcm_flashutil_nor.h" + + + +/* ---- Private Constants and Types --------------------------------------- */ + +/* #define CC_IMGUTIL_DEBUG 0 */ +#define IMGUTIL_HDR_BUF_SIZE 0x100000 +#define MTD_NAME_IMAGE "image" +#define MTD_NAME_IMAGE_UPDATE "image_update" + +typedef enum +{ + IMGUTIL_STATE_IDLE = 0, + IMGUTIL_STATE_HDR, + IMGUTIL_STATE_IMG, + IMGUTIL_STATE_NO_IMG, + IMGUTIL_STATE_ERR +} imgutil_upgrade_state_e; + +/* + * Bundled image header information related to upgrade + * (parsed, not the original header): + * - chip_family ID + * - board id (specific board, or any) + * - image size + * - image flags (compressed, etc.) + * Suggest to add: + * - image crc value + * - image version + * - image format (BCM, FLASH, CFG) + * - flash type (NOR, NAND) + */ +#define IMGHDR_CHIPID_LEN 0x8 +#define IMGHDR_BOARDID_LEN 0x10 +#define IMGHDR_VERSION_LEN 0x20 + +typedef struct +{ + UINT8 chipId[IMGHDR_CHIPID_LEN]; + UINT8 boardId[IMGHDR_BOARDID_LEN]; + UINT8 version[IMGHDR_VERSION_LEN]; + UINT32 imgSize; + UINT32 flags; + UINT32 offSet; + UINT32 crc; + CmsImageFormat format; + imgutil_flash_type_e flashType; +} imgutil_imghdr_info_t; + +/* IMGUTIL context. */ +typedef struct +{ + /* FLASH type: NAND/NOR. */ + UINT32 flashType; + UINT32 flashSize; + UINT32 eraseSize; + + /* + * Bundle header information: + * bundleHdrExistB - whether the bundle header is found. + * imgHdr - header for the desired image. + */ + UBOOL8 bundleHdrExistB; + imgutil_imghdr_info_t imgHdrInfo; + int combo_parsing_state; + Comboimg_header_tag combo_hdr_tag; + Comboimg_individual_img_tag indiv_hdr_tag; + + /* Client inputs. */ + UINT32 maxBufSize; + UBOOL8 forceWholeFlashB; + UINT32 options; + IMGUTIL_VALIDATE_IMG_FUNC clientValidateFuncP; + IMGUTIL_WRITE_IMG_FUNC clientFlashFuncP; + IMGUTIL_CAL_CRC32_FUNC calCrc32FuncP; + void *clientCtxP; + + /* + * Run time upgrade info: + * hdrBufP - pointer to the image header buffer. After the header of the + * expected image is parsed, the header is copied to imgBufP, and + * hdrBufP is not used any more. + * hdrBufSize - allocated buffer size for hdrBufP. + * imgBufP - pointer to the whole image to be flashed. not used for + * the incremental flashing case. + * imgBufSize - allocated buffer size for imgBufP. + * usrBytes - accumulated copied bytes from _write(). + * accImgSize - accumulated image size from _write(), for both whole and + * incremental cases. For the combo image case, only the expected image + * is counted. + * crc - whole image crc. + * imgStartP - starting point of the image to be flashed. + */ + UBOOL8 wholeFlashB; + imgutil_upgrade_state_e upgradeState; + UINT8 *hdrBufP; + UINT32 hdrBufSize; + UINT8 *imgBufP; + UINT32 imgBufSize; + UINT32 usrBytes; + UINT32 accImgSize; + UINT32 crc; + UINT8 *imgStartP; + UINT8 *currP; + UINT8 *endP; + IMGIF_HANDLE imgifHandle; + + /* + * Software image info: + * imgFormat - parsed image format (not from header). + * imgInfoBi - built-in image information (not from header). + * imgInfoEx - client-provided image information. + */ + UINT32 imgFormat; + imgutil_img_info_t imgInfoBi; + imgutil_img_info_t imgInfoEx; +} imgutil_ctx_t; + +#define getCtx() (&imgutilCtx) +#define getCtxByHandle(h) ((imgutil_ctx_t*)h) +#define copyDataToBucket(ctxP, usrP, copyLen) \ +{ \ + memcpy(ctxP->currP, usrP, copyLen); \ + ctxP->currP += copyLen; \ + ctxP->accImgSize += copyLen; \ + ctxP->usrBytes += copyLen; \ +} + +#if defined(CC_IMGUTIL_DEBUG) +#define imgutil_debug(fmt, arg...) \ + printf("%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) +#define DUMPIMGUTILCTX(cxtP) dumpImgutilCtx(ctxP) +#else +#define imgutil_debug(fmt, arg...) +#define DUMPIMGUTILCTX(cxtP) +#endif + +#define imgutil_error(fmt, arg...) \ + printf("ERROR[%s.%u]: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + +#define imgutil_info(fmt, arg...) \ + printf("%s.%u: " fmt "\n", __FUNCTION__, __LINE__, ##arg) + +/* ---- Private Function Prototypes --------------------------------------- */ + +static imgutil_ret_e hdrBufInit(imgutil_ctx_t *ctxP); +static imgutil_ret_e hdrBufClean(imgutil_ctx_t *ctxP); +static imgutil_ret_e imgutil_ctx_clean(imgutil_ctx_t *ctxP); + +#if defined(CC_IMGUTIL_DEBUG) +static void dumpImgutilCtx(imgutil_ctx_t *ctxP); +#endif +static UINT32 getFlashType(void); +static UBOOL8 hasEnoughDataToProcImgHdr(UINT32 bufSize); +static void parseImgHdr(imgutil_ctx_t *ctxP); +static imgutil_ret_e procSingleImgHdr(imgutil_ctx_t *ctxP); +static int procComboImgHdr(imgutil_ctx_t *ctxP, UINT8 *dataP, int len, + int *offsetP); +static int validateAndFlashConfigFile(imgutil_ctx_t *ctxP); +static int validateAndFlashWholeImage(imgutil_ctx_t *ctxP); +static imgutil_ret_e validateImageWithExtInfo(imgutil_ctx_t *ctxP, + imgutil_img_info_t *imgInfoInP); +static void imgInfoConvert(imgutil_img_info_t *imgUtilInfoP, + imgif_img_info_t *imgIfInfoP); + +/* ---- Public Variables -------------------------------------------------- */ + + +/* ---- Private Variables ------------------------------------------------- */ + +static imgutil_ctx_t imgutilCtx; + + +/* ---- Functions --------------------------------------------------------- */ + +/***************************************************************************** +* FUNCTION: img_util_get_incflash_mode +* PURPOSE: Check whether incremental flashing is supported and enabled. +* PARAMETERS: +* None. +* RETURNS: +* TRUE - supported and enabled. FALSE - else. +* NOTES: +* None. +*****************************************************************************/ +UBOOL8 img_util_get_incflash_mode(void) +{ + return imgif_get_enable_mode(); +} + +/***************************************************************************** +* FUNCTION: img_util_get_flash_info +* PURPOSE: Obtain flash info. +* PARAMETERS: + h (IN) - IMGIF context pointer. + flashInfoP (OUT) - flash info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked at any time after img_util_open(). +*****************************************************************************/ +int img_util_get_flash_info(IMGUTIL_HANDLE h, imgutil_flash_info_t *flashInfoP) +{ + imgutil_ctx_t *ctxP; + + ctxP = getCtxByHandle(h); + if ((ctxP != NULL) && (flashInfoP != NULL)) + { + flashInfoP->flashType = ctxP->flashType; + flashInfoP->flashSize = ctxP->flashSize; + flashInfoP->eraseSize = ctxP->eraseSize; + return 0; + } + + return -1; +} + +/***************************************************************************** +* FUNCTION: img_util_open +* PURPOSE: Initialize flash write context. +* PARAMETERS: +* openParmsP (IN) - pointer to the open parameters. +* RETURNS: +* Pointer to the flash write context - successful operation. +* NULL - failed operation, for example, another software upgrade already +* in progress. +* NOTES: +* During open(), if maxBufSize is 0 for the whole flashing case, +* attempt to malloc() maximum possible size. If not successful retry +* with smaller sizes. +*****************************************************************************/ +IMGUTIL_HANDLE img_util_open(imgutil_open_parms_t *openParmsP) +{ + imgutil_ctx_t *ctxP = NULL; + imgutil_ret_e ret; + + if (openParmsP == NULL) + { + imgutil_error("Invalid paramrs"); + return IMGUTIL_HANDLE_INVALID; + } + + if( bcmImg_ComboImageInit() != IMGUTIL_PROC_OK ) + return IMGUTIL_HANDLE_INVALID; + + imgutil_debug("Enter, maxBufSize=%d, forceWholeFlashB=%d, options=%d", + openParmsP->maxBufSize, openParmsP->forceWholeFlashB, openParmsP->options); + + ctxP = getCtx(); + memset(ctxP, 0x0, sizeof(imgutil_ctx_t)); + + /* Check if incremental flashing is enabled */ + if ( imgif_get_enable_mode() ) + { + /* Retrieve flashInfo from imgif api */ + imgif_flash_info_t flashInfo; + if( imgif_get_flash_info(&flashInfo) == 0 ) + { + ctxP->flashType = flashInfo.flashType; + ctxP->flashSize = flashInfo.flashSize; + ctxP->eraseSize = flashInfo.eraseSize; + } + else + { + imgutil_error("Cant retrieve flashinfo from imgif!"); + return IMGUTIL_HANDLE_INVALID; + } + } + else + { + ctxP->flashSize = bcmImg_getImageFlashSize(); + ctxP->flashType = getFlashType(); + } + + /* Reject the request if the estimated image size does not fit. */ + if ((openParmsP->maxBufSize != 0) && (openParmsP->maxBufSize > ctxP->flashSize)) + { + imgutil_error("Image size %d does not fit flash size %d.", + openParmsP->maxBufSize, ctxP->flashSize); + return IMGUTIL_HANDLE_INVALID; + } + + + ret = hdrBufInit(ctxP); + if (ret != IMGUTIL_PROC_OK) + { + imgutil_error("hdrBufInit() failed."); + return IMGUTIL_HANDLE_INVALID; + } + + + ctxP->imgStartP = ctxP->hdrBufP; + ctxP->currP = ctxP->hdrBufP; + ctxP->endP = ctxP->hdrBufP + ctxP->hdrBufSize; + + ctxP->maxBufSize = openParmsP->maxBufSize; + ctxP->forceWholeFlashB = openParmsP->forceWholeFlashB; + ctxP->options = openParmsP->options; + ctxP->calCrc32FuncP = openParmsP->calCrc32Func; + ctxP->clientValidateFuncP = openParmsP->clientValidateFuncP; + ctxP->clientFlashFuncP = openParmsP->clientFlashFuncP; + ctxP->clientCtxP = openParmsP->clientCtxP; + if (openParmsP->calStdCrcB == TRUE) + { + ctxP->calCrc32FuncP = genUtl_getCrc32Staged; + } + + if (ctxP->calCrc32FuncP != NULL) + { + ctxP->calCrc32FuncP(0, &ctxP->crc, NULL, 0); + } + + ctxP->upgradeState = IMGUTIL_STATE_HDR; + + ctxP->combo_parsing_state = combo_init; + + DUMPIMGUTILCTX(ctxP); + + return (IMGUTIL_HANDLE)ctxP; +} + +/***************************************************************************** +* FUNCTION: img_util_write +* PURPOSE: Write image block to IMGUTIL. +* PARAMETERS: +* h (IN) - IMGUTIL context pointer. +* dataP (IN) - image block data pointer. +* len (IN) - image block size. +* RETURNS: +* >=0 - number of bytes written. +* < 0 - failed operation. +* NOTES: +* None. +*****************************************************************************/ +int img_util_write(IMGUTIL_HANDLE h, UINT8 *dataP, int len) +{ + imgutil_ctx_t *ctxP; + int remainLen = 0; + int copyLen = 0; + int newLen = len; + int skipTailLen = 0; + int expectedTailLen = 0; + int writeBytes = 0; + int comboParseRetVal = 0; + UINT8 *usrP = NULL; + int offset = 0; + imgutil_ret_e ret; + + imgutil_debug("Enter, len=%d.", len); + + if ((h == NULL) || (dataP == NULL)) + { + imgutil_error("Invalid params"); + return -1; + } + + ctxP = getCtxByHandle(h); + + DUMPIMGUTILCTX(ctxP); + + if (ctxP->calCrc32FuncP != NULL) + { + ctxP->calCrc32FuncP(1, &ctxP->crc, dataP, len); + } + + if (!bcmImg_ComboImageParsingDone()) + { + comboParseRetVal = procComboImgHdr(ctxP, dataP, newLen, &offset); + if (comboParseRetVal < 0) /* Indicates acute failure. */ + { + writeBytes = -1; + ctxP->upgradeState = IMGUTIL_STATE_NO_IMG; + return -1; + } + + if (bcmImg_ComboImageParsingDone()) + { + if (bcmImg_IsValidCombo()) + { + imgutil_info("combo parsing is done and valid \n"); + ctxP->usrBytes += offset; + dataP += offset; + newLen -= offset; + imgutil_debug("procComboImgHdr(), dataP=%p, len=%d, offset=%d", + dataP, newLen, offset); + + imgutil_accept_range_ctx_t *ar_ctx = (imgutil_accept_range_ctx_t*)(ctxP->clientCtxP); + + if(ar_ctx->accept_ranges && ar_ctx->range_begin) + { + imgutil_info("Server supports Range. Need to restart download with Range header. exiting img_util_write\n"); + ctxP->usrBytes = 0; + ctxP->crc = 0; + //i think the next line should be removed + //ctxP->bundleHdrExistB = FALSE; + //bcmImg_ComboImageInit(); + goto write_exit; + } + } + else + { + imgutil_info("This isn't a combo image, proceed to test other image types\n"); + /* Not combo, continue. */ + } + } + else /* Still parsing header or rolling to the image. */ + { + ctxP->usrBytes += newLen; + writeBytes = newLen; + offset = 0; + goto write_exit; + } + } + + /* + * If the expected image is received completely, no need to buffer + * following images. + */ + if ((ctxP->upgradeState == IMGUTIL_STATE_IMG) && + (ctxP->bundleHdrExistB == TRUE)) + { + if ((ctxP->accImgSize + newLen) >= ctxP->indiv_hdr_tag.image_len) + { + expectedTailLen = ctxP->indiv_hdr_tag.image_len - ctxP->accImgSize; + skipTailLen = newLen - expectedTailLen; + offset += skipTailLen; + newLen = expectedTailLen; + if (newLen == 0) + { + goto write_exit; + } + } + } + + remainLen = newLen; + + /* Incremental flashing. */ + if ((ctxP->upgradeState == IMGUTIL_STATE_IMG) && + (ctxP->imgifHandle != NULL)) + { + writeBytes = imgif_write(ctxP->imgifHandle, dataP, newLen); + if ((writeBytes < 0) || (writeBytes != newLen)) + { + imgutil_error("imgif_write() failed, towrite=%d, written=%d", + newLen, writeBytes); + } + else + { + ctxP->accImgSize += newLen; + ctxP->usrBytes += newLen; + } + + return (writeBytes + offset); + } + + usrP = dataP; + do + { + copyLen = ((ctxP->currP + remainLen) > ctxP->endP) ? + (ctxP->endP - ctxP->currP) : remainLen; + imgutil_debug("Copy from user, usrP=%p, copyLen=%d.", usrP, copyLen); + if (copyLen == 0) + { + break; + } + + /* Either a header buffer or an image buffer. */ + copyDataToBucket(ctxP, usrP, copyLen); + + usrP += copyLen; + remainLen -= copyLen; + writeBytes += copyLen; + + if ((ctxP->upgradeState == IMGUTIL_STATE_HDR) && + (hasEnoughDataToProcImgHdr(ctxP->accImgSize) == TRUE)) + { + parseImgHdr(ctxP); + ret = procSingleImgHdr(ctxP); + if (ret != IMGUTIL_PROC_OK) + { + /* Abort. */ + writeBytes = -1; + break; + } + } + + DUMPIMGUTILCTX(ctxP); + + } while (remainLen > 0); + + if (writeBytes != newLen) + { + imgutil_error("Error, len=%d, written=%d", newLen, writeBytes); + return -1; + } + +write_exit: + imgutil_debug("Exit, len=%d, written=%d", len, writeBytes + offset); + + DUMPIMGUTILCTX(ctxP); + + return (writeBytes + offset); +} + +/***************************************************************************** +* FUNCTION: img_util_close +* PURPOSE: Close IMGUTIL context in successful condition. +* PARAMETERS: +* h (IN) - IMGUTIL context pointer. +* imgInfoInP (IN) - image info obtained externally. The client protocol +* may provide additional image integrity (size, CRC) information at +* the end of the upgrade. +* imgInfoOutP (OUT) - info (e.g. version) obtained from the image, +* either from the bundle header or from the image itself. A client +* may need the information. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* The client should provide callback functions for the configuration +* file validation and upgrade, which are tightly coupled with CMS. +* +* The flashing time for a whole image can be long (> 10s). Certain +* client protocol specification (e.g. OMCI) expects timely responses +* from the client agent during the flashing operation. To avoid the +* blocking condition, the client may choose to invoke this API from a +* different thread. +*****************************************************************************/ +int img_util_close(IMGUTIL_HANDLE h, imgutil_img_info_t *imgInfoInP, + imgutil_img_info_t *imgInfoOutP) +{ + imgutil_ctx_t *ctxP; + imgutil_ret_e ret = IMGUTIL_PROC_OK; + int rc = -1; + + if (h == NULL) + { + imgutil_error("Invalid params"); + return -1; + } + + imgutil_debug("Enter, imgInfoInP=%p, imgInfoOutP=%p", + imgInfoInP, imgInfoOutP); + + ctxP = getCtxByHandle(h); + + DUMPIMGUTILCTX(ctxP); + + if (ctxP->upgradeState == IMGUTIL_STATE_NO_IMG) + goto close_exit; + + if (ctxP->upgradeState != IMGUTIL_STATE_IMG) + { + imgutil_error("Invalid state"); + goto close_exit; + } + + if (ctxP->calCrc32FuncP != NULL) + { + ctxP->calCrc32FuncP(2, &ctxP->crc, NULL, 0); + } + + if (imgInfoInP != NULL) + { + ret = validateImageWithExtInfo(ctxP, imgInfoInP); + if (ret != IMGUTIL_PROC_OK) + { + imgutil_error("validateImageWithExtInfo() failed"); + goto close_exit; + } + } + + if (ctxP->wholeFlashB == TRUE) + { + if (ctxP->imgFormat == CMS_IMAGE_FORMAT_XML_CFG) + { + if ((ctxP->clientValidateFuncP == NULL) || + (ctxP->clientFlashFuncP == NULL)) + { + imgutil_error("Invalid client function for config file"); + goto close_exit; + } + + rc = validateAndFlashConfigFile(ctxP); + } + else + { + rc = validateAndFlashWholeImage(ctxP); + } + } + else + { + /* Incrementatl flashing. */ + rc = imgif_close(ctxP->imgifHandle, 0); + } + + if ((rc >= 0) && (imgInfoOutP != NULL)) + { + imgInfoOutP->bitmask = IMG_INFO_BITMASK_SIZE; + imgInfoOutP->size = ctxP->usrBytes; + } + +close_exit: + imgutil_ctx_clean(ctxP); + + return rc; +} + +/***************************************************************************** +* FUNCTION: img_util_abort +* PURPOSE: Close IMGUTIL context in error condition. +* PARAMETERS: +* h (IN) - IMGUTIL context pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* Client may stop an upgrade at any time, when there is an operator +* command, protocol failure, or unmatched image size and/or CRC values +* between IMGUTIL and client. +*****************************************************************************/ +int img_util_abort(IMGUTIL_HANDLE h) +{ + imgutil_ctx_t *ctxP; + int rc = 0; + + imgutil_debug("Enter"); + + if (h == NULL) + { + imgutil_error("Invalid params"); + return -1; + } + + ctxP = getCtxByHandle(h); + DUMPIMGUTILCTX(ctxP); + + if (ctxP->imgifHandle != NULL) + { + rc = imgif_close(ctxP->imgifHandle, 1); + } + + imgutil_ctx_clean(ctxP); + imgutil_info("rc = %d", rc); + + return rc; +} + +/***************************************************************************** +* FUNCTION: img_util_get_imginfo +* PURPOSE: Get image information from library. +* PARAMETERS: +* h (IN) - IMGUTIL context pointer. +* bitmask (IN) - image info bitmask. +* imgInfoP (OUT) - image info pointer. +* RETURNS: +* 0 - successful operation. +* < 0 - failed operation. +* NOTES: +* This function may be invoked right before img_util_close(), after last +* img_util_write(). +*****************************************************************************/ +int img_util_get_imginfo(IMGUTIL_HANDLE h, imgutil_info_src_e src, + UINT32 bitmask, imgutil_img_info_t *imgInfoP) +{ + imgutil_ctx_t *ctxP; + imgutil_ret_e ret; + UINT32 finalCrc; + int rc = 0; + + imgutil_debug("Enter"); + + if ((h == NULL) || (imgInfoP == NULL)) + { + imgutil_error("Invalid params"); + return -1; + } + + ctxP = getCtxByHandle(h); + + if (src == IMGINFO_SRC_CALCOMBO) + { + if (bitmask & IMGUTIL_IMGINFO_BIT_SIZE) + { + imgInfoP->bitmask |= IMGUTIL_IMGINFO_BIT_SIZE; + imgInfoP->size = ctxP->usrBytes; + } + + if (bitmask & IMGUTIL_IMGINFO_BIT_CRC) + { + if (ctxP->calCrc32FuncP != NULL) + { + finalCrc = ctxP->crc; + ctxP->calCrc32FuncP(2, &finalCrc, NULL, 0); + imgInfoP->bitmask |= IMGUTIL_IMGINFO_BIT_CRC; + imgInfoP->crc = finalCrc; + } + } + } + else if (src == IMGINFO_SRC_BLTIN) + { + if (bitmask & IMGUTIL_IMGINFO_BIT_VERSION) + { + if (ctxP->wholeFlashB == TRUE) + { + ret = bcmImg_getImageVersion((char*)ctxP->imgBufP, + ctxP->accImgSize, (char*)imgInfoP->version, + IMGUTIL_VERSION_LEN); + if (ret == IMGUTIL_PROC_OK) + { + imgInfoP->bitmask |= IMGUTIL_IMGINFO_BIT_VERSION; + } + else + { + imgutil_error("bcmImg_getImageVersion() failed."); + rc = -1; + } + } + else + { + devCtl_getImageVersion(getUpgradePartition(), (char*)imgInfoP->version, + IMGUTIL_VERSION_LEN); + } + } + } + + return rc; +} + + +/* ---- Private Functions ------------------------------------------------- */ + +/* Allocate a small buffer to store the image header or the whole config. */ +static imgutil_ret_e hdrBufInit(imgutil_ctx_t *ctxP) +{ + UINT32 hdrBufSize; + UINT32 configFlashSize; + + configFlashSize = bcmImg_getConfigFlashSize(); + hdrBufSize = (configFlashSize > IMGUTIL_HDR_BUF_SIZE)? + configFlashSize : IMGUTIL_HDR_BUF_SIZE; + + ctxP->hdrBufP = malloc(hdrBufSize); + if (ctxP->hdrBufP == NULL) + { + imgutil_error("malloc(%d) failed.", hdrBufSize); + goto init_exit; + } + + ctxP->hdrBufSize = hdrBufSize; + return IMGUTIL_PROC_OK; + +init_exit: + ctxP->hdrBufSize = 0; + return IMGUTIL_PROC_ERR; +} + +static imgutil_ret_e hdrBufClean(imgutil_ctx_t *ctxP) +{ + if (ctxP->hdrBufP != NULL) + { + free(ctxP->hdrBufP); + ctxP->hdrBufP = NULL; + } + + ctxP->hdrBufSize = 0; + return IMGUTIL_PROC_OK; +} + +/* Allocate the buffer to store the whole image. */ +static imgutil_ret_e imgBufInit(imgutil_ctx_t *ctxP) +{ + UINT8 *bufP = NULL; + UINT32 bufSize; + + bufP = bcmImg_allocImgBuf(ctxP->maxBufSize, &bufSize); + if (bufP == NULL) + { + imgutil_error("bcmImg_allocImgBuf(%d) failed.", ctxP->maxBufSize); + goto init_exit; + } + + printf("imgutil: allocated %d byte buffer to hold image.", bufSize); + ctxP->imgBufP = bufP; + ctxP->imgBufSize = bufSize; + return IMGUTIL_PROC_OK; + +init_exit: + ctxP->imgBufSize = 0; + return IMGUTIL_PROC_ERR; +} + +static imgutil_ret_e imgBufClean(imgutil_ctx_t *ctxP) +{ + if (ctxP->imgBufP != NULL) + { + free(ctxP->imgBufP); + ctxP->imgBufP = NULL; + } + + ctxP->imgBufSize = 0; + return IMGUTIL_PROC_OK; +} + +static imgutil_ret_e imgutil_ctx_clean(imgutil_ctx_t *ctxP) +{ + hdrBufClean(ctxP); + imgBufClean(ctxP); + + memset(ctxP, 0x0, sizeof(imgutil_ctx_t)); + + DUMPIMGUTILCTX(ctxP); + + return IMGUTIL_PROC_OK; +} + +#if defined(CC_IMGUTIL_DEBUG) +static void dumpImgutilCtx(imgutil_ctx_t *ctxP) +{ + printf("--------------------------------------------------------------\n"); + printf("\tFlash: type=%d, size=%d, eraseSize=%d\n", + ctxP->flashType, ctxP->flashSize, ctxP->eraseSize); + printf("\tUser input: maxBufSize=%d, forceWholeFlashB=%d, options=%d\n", + ctxP->maxBufSize, ctxP->forceWholeFlashB, ctxP->options); + printf("\tBuffer: hdrBufP=%p, hdrBufSize=%d, imgBufP=%p, imgBufSize=%d\n", + ctxP->hdrBufP, ctxP->hdrBufSize, ctxP->imgBufP, ctxP->imgBufSize); + printf("\tPointer: currP=%p, endP=%p\n", ctxP->currP, ctxP->endP); + printf("\tUpgrade: format=%d, wholeFlashB=%d, state=%d, usrBytes=%d, " + "accImgSize=%d\n", + ctxP->imgFormat, ctxP->wholeFlashB, ctxP->upgradeState, ctxP->usrBytes, + ctxP->accImgSize); + if (ctxP->bundleHdrExistB) + { + printf("\tCombo Hdr: len=%d, crc=0x%08x, count=%d, " + "flags=0x%08x, noffset=%d, ext=%d\n", + ctxP->combo_hdr_tag.header_len, ctxP->combo_hdr_tag.header_crc, + ctxP->combo_hdr_tag.image_count, ctxP->combo_hdr_tag.header_flags, + ctxP->combo_hdr_tag.next_tag_offset, + ctxP->combo_hdr_tag.extended_combo_header); + printf("\tIndiv Hdr: chipid=0x%x, imageLen=%d, offset=%d, " + "flags=0x%08x, noffset=%d, ext=%d\n", + ctxP->indiv_hdr_tag.chip_id, ctxP->indiv_hdr_tag.image_len, + ctxP->indiv_hdr_tag.image_offset, ctxP->indiv_hdr_tag.image_flags, + ctxP->indiv_hdr_tag.next_tag_offset, + ctxP->indiv_hdr_tag.extended_image_header); + } + printf("--------------------------------------------------------------\n"); +} +#endif + +UINT32 getFlashType(void) +{ + unsigned int flags = 0; + UINT32 flashType = 0; + int ret; + + ret = getFlashInfo(&flags); + if (ret >= 0) /* OK */ + { + flashType = flags; + } + else + { + imgutil_error("getFlashInfo() failed, ret=%d.", ret); + } + + return flashType; +} + +int validateAndFlashConfigFile(imgutil_ctx_t *ctxP) +{ + int rc = 0; + + imgutil_debug("Enter, bufP=%p, size=%d", ctxP->imgStartP, ctxP->accImgSize); + + /* Config file always in hdrBufP. */ + rc = ctxP->clientValidateFuncP(ctxP->imgStartP, ctxP->accImgSize, + ctxP->clientCtxP); + if (rc < 0) + { + imgutil_error("clientValidateFuncP() failed"); + return -1; + } + + rc = ctxP->clientFlashFuncP(ctxP->imgStartP, ctxP->accImgSize, + ctxP->clientCtxP); + if (rc < 0) + { + imgutil_error("clientFlashFuncP() failed"); + return -1; + } + + return rc; +} + +static int validateAndFlashWholeImage(imgutil_ctx_t *ctxP) +{ + int noReboot = 0; + CmsRet cmsRet; + + imgutil_debug("Enter, bufP=%p, size=%d, format=%d, options=%d", + ctxP->imgBufP, ctxP->accImgSize, ctxP->imgFormat, ctxP->options); + + ctxP->imgFormat = bcmImg_validateImage((char*)ctxP->imgBufP, + ctxP->accImgSize); + if (ctxP->imgFormat == CMS_IMAGE_FORMAT_INVALID) + { + imgutil_error("bcmImg_validateImage() failed"); + return -1; + } + + cmsRet = bcmImg_flashImage((char*)ctxP->imgBufP, ctxP->accImgSize, + ctxP->imgFormat, ctxP->options, &noReboot); + if (cmsRet != CMSRET_SUCCESS) + { + imgutil_error("bcmImg_flashImage() failed"); + return -1; + } + + printf("Image flash done\n"); + imgutil_debug("noReboot=%d", noReboot); + if (noReboot == 0) + { + imgutil_debug("bcmImg_reboot()"); + bcmImg_reboot(); + } + + return 0; +} + +static UBOOL8 hasEnoughDataToProcImgHdr(UINT32 bufSize) +{ + UBOOL8 enough = FALSE; + + if ((bufSize >= sizeof(FILE_TAG)) && + (bufSize >= CMS_CONFIG_FILE_DETECTION_LENGTH) && + (bufSize >= sizeof(Comboimg_header_tag))) + { + enough = TRUE; + } + + return enough; +} + +/* + * Scan through the combo image till reach the expected individual image, + * pass the single image pointer back to caller. + */ +static int procComboImgHdr(imgutil_ctx_t *ctxP, UINT8 *dataP, int len, + int *offsetP) +{ + UINT32 imageLen; + UINT32 consumed; + imgutil_ret_e utilRet; + + utilRet = bcmImg_ComboImageParseHeader((char*)dataP, + len, &consumed, &imageLen, &ctxP->combo_parsing_state, + &(ctxP->combo_hdr_tag), &(ctxP->indiv_hdr_tag), ctxP->clientCtxP); + + if (utilRet == IMGUTIL_PROC_NOT_FOUND) + return -1; + else if (utilRet != IMGUTIL_PROC_OK) + { + imgutil_error("bcmImg_ComboImageParseHeader() failed," + "dataP=%p, len=%d, consumed=%d, imageLen=%d, state=%d", + dataP, len, consumed, imageLen, ctxP->combo_parsing_state); + return -1; + } + + if (bcmImg_IsValidCombo()) + { + ctxP->bundleHdrExistB = TRUE; + } + + *offsetP = consumed; + return 0; +} + +/* + * This function is used to parse a single image only (standalone single + * image or an individual image inside the combo. + */ +static void parseImgHdr(imgutil_ctx_t *ctxP) +{ + CmsImageFormat imgFormat = CMS_IMAGE_FORMAT_FLASH; + + imgutil_debug("Enter, imgStartP=%p, accImgSize=%d", + ctxP->imgStartP, ctxP->accImgSize); + + imgFormat = bcmImg_parseImgHdr(ctxP->imgStartP, ctxP->accImgSize); + ctxP->imgFormat = imgFormat; + ctxP->upgradeState = IMGUTIL_STATE_IMG; + + imgutil_debug("Exit, imgStartP=%p, accImgSize=%d", + ctxP->imgStartP, ctxP->accImgSize); +} + +/* + * This function is used to process a single image only (standalone single + * image or an individual image inside the combo. + */ +static imgutil_ret_e procSingleImgHdr(imgutil_ctx_t *ctxP) +{ + int byteCount; + + if (ctxP->imgFormat == CMS_IMAGE_FORMAT_XML_CFG) + { + /* Do nothing, the hdrBuf is sufficient for XML_CFG. */ + ctxP->wholeFlashB = TRUE; + goto proc_exit; + } + + /* Only apply forceWholeFlashB flag to CMS_IMAGE_FORMAT_FLASH. */ +#ifdef DESKTOP_LINUX + if ((ctxP->forceWholeFlashB == TRUE) || + (ctxP->flashType == FLASH_INFO_FLAG_NOR)) +#else + if ((ctxP->forceWholeFlashB == TRUE) || + ((ctxP->flashType == FLASH_INFO_FLAG_NOR) && (0 == norIsNewFlashLayout()))) +#endif + { + ctxP->wholeFlashB = TRUE; + } + + if (ctxP->wholeFlashB == TRUE) + { + if (imgBufInit(ctxP) != IMGUTIL_PROC_OK) + { + imgutil_error("imgBufInit() failed."); + return IMGUTIL_PROC_ERR; + } + + /* Copy the content from header buffer to image buffer. */ + memcpy(ctxP->imgBufP, ctxP->imgStartP, ctxP->accImgSize); + ctxP->currP = ctxP->imgBufP + ctxP->accImgSize; + ctxP->endP = ctxP->imgBufP + ctxP->imgBufSize; + + /* Header buffer is not needed from this point on. */ + hdrBufClean(ctxP); + ctxP->imgStartP = ctxP->imgBufP; + } + else + { + /* Call incremental flashing API, flush out accumulated buffer. */ + ctxP->imgifHandle = imgif_open(NULL, ctxP->calCrc32FuncP); + if (ctxP->imgifHandle == NULL) + { + imgutil_error("imgif_open() failed."); + return IMGUTIL_PROC_ERR; + } + + byteCount = imgif_write(ctxP->imgifHandle, (UINT8*)ctxP->imgStartP, + ctxP->accImgSize); + if ((byteCount < 0) || ((UINT32)byteCount != ctxP->accImgSize)) + { + imgutil_error("imgif_write() failed, towrite=%d, written=%d", + ctxP->accImgSize, byteCount); + return IMGUTIL_PROC_ERR; + } + + /* Header buffer is not needed from this point on. */ + hdrBufClean(ctxP); + ctxP->currP = NULL; + ctxP->endP = NULL; + } + +proc_exit: + return IMGUTIL_PROC_OK; +} + +imgutil_ret_e validateImageWithExtInfo(imgutil_ctx_t *ctxP, + imgutil_img_info_t *imgInfoInP) +{ + imgutil_ret_e rc = IMGUTIL_PROC_OK; + + if ((imgInfoInP->bitmask & IMG_INFO_BITMASK_SIZE) && + (imgInfoInP->size != ctxP->usrBytes)) + { + imgutil_error("Unmatched file size values, ext=%d, cal=%d", + imgInfoInP->size, ctxP->usrBytes); + rc = IMGUTIL_PROC_ERR; + } + + if ((ctxP->bundleHdrExistB == FALSE) && + (ctxP->imgifHandle != NULL)) + { + imgif_img_info_t imgIfInfo; + + memset(&imgIfInfo, 0x0, sizeof(imgIfInfo)); + imgInfoConvert(imgInfoInP, &imgIfInfo); + imgif_set_image_info(ctxP->imgifHandle, &imgIfInfo); + } + + return rc; +} + +static void imgInfoConvert(imgutil_img_info_t *imgUtilInfoP, + imgif_img_info_t *imgIfInfoP) +{ + imgIfInfoP->bitmask |= (imgUtilInfoP->bitmask & IMGUTIL_IMGINFO_BIT_SIZE) ? + IMG_INFO_BITMASK_SIZE : 0; + imgIfInfoP->bitmask |= (imgUtilInfoP->bitmask & IMGUTIL_IMGINFO_BIT_CRC) ? + IMG_INFO_BITMASK_CRC : 0; + imgIfInfoP->size = imgUtilInfoP->size; + imgIfInfoP->crc = imgUtilInfoP->crc; +} + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/commit.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/commit.sh new file mode 100755 index 00000000000..8e6138e2cad --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/commit.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# commit image if booted but not committed and /data/commit_image_after_reboot file exists + +if [ -e /data/commit_image_after_reboot ]; then + rm /data/commit_image_after_reboot + BOOTSTATE="$(/bin/bcm_bootstate)" + + boot_part="$(/bin/bcm_bootstate | grep 'Booted Partition')" + first_seq="$(/bin/bcm_bootstate | grep 'First partition sequence number:')" + second_seq="$(/bin/bcm_bootstate | grep 'Second partition sequence number:')" + + # cut all before ":" + boot_part=${boot_part##*":"}; + first_seq=${first_seq##*":"}; + second_seq=${second_seq##*":"}; + + if [ "$first_seq" == " 0" ] && [ "$second_seq" == " 999" ]; then + first_seq="1000" + fi + + if [ "$second_seq" == " 0" ] && [ "$first_seq" == " 999" ]; then + second_seq="1000" + fi + + if [ "$boot_part" == " First" ] && [ "$first_seq" -gt "$second_seq" ]; then + echo "committing first partition image" + /bin/bcm_bootstate 5 + fi + + if [ "$boot_part" == " Second" ] && [ "$second_seq" -gt "$first_seq" ]; then + echo "committing second partition image" + /bin/bcm_bootstate 7 + fi +fi + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/prebuilt/libbcm_flashutil.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/prebuilt/libbcm_flashutil.so new file mode 100755 index 00000000000..30747c0573d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_flashutil/prebuilt/libbcm_flashutil.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/Bcmbuild.mk new file mode 100644 index 00000000000..b81233585b6 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/Bcmbuild.mk @@ -0,0 +1,47 @@ +LIB := libbcm_util.so + +default: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH=$(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/include +ALLOWED_INCLUDE_PATHS := -I . \ + -I $(BUILD_DIR)/userspace/public/include \ + -I $(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I $(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I $(HEADER_INSTALL_DIR) + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + +all install: clean_legacy + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with dual makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + + +shell: + bash -i diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/Makefile new file mode 100755 index 00000000000..7e99865dca0 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/Makefile @@ -0,0 +1,45 @@ +LIB = libbcm_util.so + +OBJS = bcm_timestamp.o bcm_ulog.o bcm_net.o bcm_fsutils.o \ + bcm_boardutils.o bcm_ethswutils.o bcm_strutils.o + +CFLAGS += -Werror -Wfatal-errors -Wno-stringop-truncation -I$(HND_SRC)/router-sysdep/sys_util/ -I$(HND_SRC)/userspace/public/include/linux/ -I$(HND_SRC)/userspace/public/include/ +ifneq ($(strip $(BCM4906_504)),) +CFLAGS += -I$(HND_SRC)/userspace/public/include/ -I$(HND_SRC)/bcmdrivers/opensource/include/bcm963xx/ -I$(HND_SRC)/shared/opensource/include/bcm963xx/ +endif + +# These are public API headers needed by other apps which want to call this lib. +# Private/internal headers should not be listed here. +HEADERS = bcm_ulog.h bcm_timestamp.h bcm_net.h bcm_fsutils.h \ + bcm_boardutils.h bcm_ethswutils.h bcm_strutils.h + +all: $(LIB) + +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/public/include + +install: $(LIB) + mkdir -p $(LIB_INSTALL_DIR) + install -t $(LIB_INSTALL_DIR) $(LIB) + mkdir -p $(INSTALLDIR)/lib + install -t $(INSTALLDIR)/lib $(LIB) + mkdir -p $(HEADER_INSTALL_DIR) + install -p -m 444 -t $(HEADER_INSTALL_DIR) $(addprefix $(mdir)/,$(HEADERS)) + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(addprefix $(HEADER_INSTALL_DIR)/,$(HEADERS)) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive -ldl + + +# Set VPATH because we want to compile in a seperate dir than source. +name := $(lastword $(MAKEFILE_LIST)) +mdir := $(realpath $(dir $(name))) +VPATH=$(mdir) + +# Generate and use dependencies. +CFLAGS += -MD +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/autodetect new file mode 100644 index 00000000000..383e87b2477 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/autodetect @@ -0,0 +1 @@ +dependson: public/libs/sys_util public/libs/gen_util diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_boardutils.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_boardutils.c new file mode 100644 index 00000000000..584c2a0d46c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_boardutils.c @@ -0,0 +1,233 @@ +/*********************************************************************** + * + * Copyright (c) 2020 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2020:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "bcm_boardutils.h" +#include "bcm_ulog.h" +#include "cms_version.h" + +int bcmUtl_isBootloaderUboot(void) +{ + struct stat statbuf; + int rc; + + // UBoot creates a /proc/environment dir, CFE does not. + rc = stat("/proc/environment", &statbuf); + if (rc == 0) + return 1; // found, bootloader is UBoot, return TRUE. + + // Bootloader is CFE. Return FALSE. + return 0; +} + + +BcmRet bcmUtl_getManufacturer(char *buf, UINT32 bufLen) +{ + const char *m = "Broadcom"; + UINT32 len = strlen(m); + + if (buf == NULL) + return BCMRET_INVALID_ARGUMENTS; + if (bufLen < len+1) + return BCMRET_RESOURCE_EXCEEDED; + + strcpy(buf, m); + return BCMRET_SUCCESS; +} + + +BcmRet bcmUtl_getHardwareVersion(char *buf, UINT32 bufLen) +{ + char *hw_version = "tmp_hardware1.0"; + UINT32 len = strlen(hw_version); + + if (buf == NULL) + return BCMRET_INVALID_ARGUMENTS; + if (bufLen < len+1) + return BCMRET_RESOURCE_EXCEEDED; + + strcpy(buf, hw_version); + return BCMRET_SUCCESS; +} + + +BcmRet bcmUtl_getSoftwareVersion(char *buf, UINT32 bufLen) +{ + UINT32 len = strlen(CMS_RELEASE_VERSION); + + if (buf == NULL) + return BCMRET_INVALID_ARGUMENTS; + if (bufLen < len+1) + return BCMRET_RESOURCE_EXCEEDED; + + strcpy(buf, CMS_RELEASE_VERSION); + return BCMRET_SUCCESS; +} + + +BcmRet bcmUtl_getBaseMacAddress(char *macAddrBuf) +{ + const char *fileName = "/proc/environment/basemacaddr"; + const char *fileName2 = "/proc/environment/ethaddr"; + char buf[32]={0}; + int len, xlen=17; // weird: fgets reads in phantom extra chars, limit to 17. + FILE *fp = NULL; + + if (macAddrBuf == NULL) + return BCMRET_INVALID_ARGUMENTS; + + if ((fp = fopen(fileName, "r")) == NULL) + { + bcmuLog_debug("failed to open file %s, try alternate", fileName); + if ((fp = fopen(fileName2, "r")) == NULL) + { + bcmuLog_error("could not open %s (or %s)", fileName2, fileName); + return BCMRET_INTERNAL_ERROR; + } + } + + if( NULL == fgets(buf, xlen+1, fp) ) + { + bcmuLog_error("Could not read %s", fileName); + fclose(fp); + return BCMRET_INTERNAL_ERROR; + } + fclose(fp); + + len = strlen(buf); + bcmuLog_notice("len=%d read in buffer=%s", len, buf); + if (len != xlen) + { + bcmuLog_error("Unexpected mac addr len %d (expected %d)", len, xlen); + return BCMRET_INTERNAL_ERROR; + } + + memcpy(macAddrBuf, buf, xlen); // xlen is 17, exact length of mac addr + return BCMRET_SUCCESS; +} + + +BcmRet bcmUtl_getSerialNumber(char *buf, UINT32 bufLen) +{ + char macAddrBuf[32]={0}; + int i; + BcmRet ret; + + if (bufLen < 13) // macAddr without colons is 12+null term=13 + return BCMRET_RESOURCE_EXCEEDED; + + ret = bcmUtl_getBaseMacAddress(macAddrBuf); + if (ret != BCMRET_SUCCESS) + { + bcmuLog_error("Could not get BaseMacAddress, ret=%d", ret); + return ret; + } + + /* + * Just keep old SDK serialNumber format. + * remove ':' and convert uppercase letters to lowercase letters + */ + for (i = 0; i < 18; i++) + { + if (macAddrBuf[i] == ':') + continue; + + if ((macAddrBuf[i] >= 'A') && (macAddrBuf[i] <= 'F')) + *(buf++) = macAddrBuf[i] + 32; + else + *(buf++) = macAddrBuf[i]; + } + + return BCMRET_SUCCESS; +} + + +BcmRet bcmUtl_getBootloaderVersion(char* versionBuf, UINT32 bufLen) +{ + char strBuf[256]={0}; + const char *fileName = "/sys/firmware/devicetree/base/uboot-version"; + UINT32 len; + FILE *fp = NULL; + + if (versionBuf == NULL) + { + bcmuLog_error("NULL versionBuf!"); + return BCMRET_INVALID_ARGUMENTS; + } + + if ((fp = fopen(fileName, "r")) == NULL) + { + bcmuLog_notice("failed to open file %s. Could be cfe boot image.", fileName); + return BCMRET_INTERNAL_ERROR; + } + + if( NULL == fgets(strBuf, sizeof(strBuf)-1, fp) ) + { + bcmuLog_error("Could not read %s", fileName); + fclose(fp); + return BCMRET_INTERNAL_ERROR; + } + fclose(fp); + + len = strlen(strBuf); + bcmuLog_notice("got len=%d str=%s", len, strBuf); + if (len >= bufLen) + { + bcmuLog_error("versionBuf buffer (len=%d) is too small, need %d", + bufLen, len+1); + return BCMRET_INTERNAL_ERROR; + } + + snprintf(versionBuf, bufLen, "%s", strBuf); + return BCMRET_SUCCESS; +} + + +void bcmUtl_startRebootWatchdog() +{ + // stop existing wdtd + if ( system("wdtctl -d stop") != 0 ) + bcmuLog_error("Failed to run wdtctl cmd."); + + // start one final watchdog timer. Control must reach UBoot before + // this timer expires. (Well, actually, if control does not reach UBoot, + // that is ok too because the timer will expire, the system will reset, + // and we will go into UBoot anyways. But this timer will prevent a hang.) + if ( system("wdtctl -t 60 start") != 0 ) + bcmuLog_error("Failed to run wdtctl cmd."); +} + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_boardutils.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_boardutils.h new file mode 100644 index 00000000000..c12936dd327 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_boardutils.h @@ -0,0 +1,115 @@ +/*********************************************************************** + * + * Copyright (c) 2020 Broadcom Ltd + * All Rights Reserved + * + * <:label-BRCM:2020:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * +************************************************************************/ + +#ifndef __BCM_BOARDUTILS_H__ +#define __BCM_BOARDUTILS_H__ + +#include "number_defs.h" +#include "bcm_retcodes.h" + +#if defined __cplusplus +extern "C" { +#endif + +/*!\file bcm_boardutils.h + * \brief Helper functions for various uboot and board parameter access + * functions that do not need an ioctl. + */ + + +/** Return 1 if system bootloader is UBoot, otherwise, return 0. */ +int bcmUtl_isBootloaderUboot(void); + + +/** Copy the name of the manufacturer to the given buf. + * + * This function should only be used in the DESKTOP_LINUX mode, but if + * it is called on a real gateway build, it will return /. + * + * @param buf (OUT) Buffer to hold the data. + * @param bufLen (IN) Length of the buffer. If the buffer is not large + * enough to hold the path, an error will be returned. + * @return BcmRet enum. + */ +BcmRet bcmUtl_getManufacturer(char *buf, UINT32 bufLen); + + +/** Copy the hardware version to the given buf. + * The behavior is the same as getManufacturer. + */ +BcmRet bcmUtl_getHardwareVersion(char *buf, UINT32 bufLen); + +/** Copy the Software version to the given buf. + * The behavior is the same as getManufacturer. + */ +BcmRet bcmUtl_getSoftwareVersion(char *buf, UINT32 bufLen); + +/** Get the base mac address. + * + * @param macAddrBuf (IN) Buf must be at least 17 bytes. Note this API copies + * the exact 17 bytes of mac address into the buffer. It does not + * write a terminating null into the buffer. + * + * @return BcmRet enum. +*/ +BcmRet bcmUtl_getBaseMacAddress(char *macAddrBuf); + +/** Get the serial number (just the mac address with colons stripped out). + * + * @param serialNumBuf (IN) buffer to hold the serial number. + * @param bufLen (IN) Length of the buffer. If the buffer is not large + * enough to hold the path, an error will be returned. + * + * @ret BcmRet enum. + */ +BcmRet bcmUtl_getSerialNumber(char *buf, UINT32 bufLen); + +/** Get the UBOOT loader version number. + * + * @param versionBuf (IN) buffer to hold the version number. + * @param bufLen (IN) Length of the buffer. If the buffer is not large + * enough to hold the path, an error will be returned. + * + * @ret BcmRet enum. + */ +BcmRet bcmUtl_getBootloaderVersion(char* versionBuf, UINT32 bufLen); + +/** Start a watchdog timer for reboot. + * + * See userspace/public/apps/wdtctl/README.txt for details on how this + * function is used to implement the Firmware Upgrade Watchdog Timer feature. + */ +void bcmUtl_startRebootWatchdog(); + +#if defined __cplusplus +}; +#endif +#endif /* __BCM_BOARDUTILS_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ethswutils.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ethswutils.c new file mode 100644 index 00000000000..3b9d3dc809a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ethswutils.c @@ -0,0 +1,231 @@ +/*********************************************************************** + * + * Copyright (c) 2020 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2020:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + + +/*!\file bcm_ethswutil.c + * \brief Some utility functions for querying the ethernet switch. Does not + * depend on ethswctl though. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcmnet.h" // for ifreq_ext +#include "bcm_retcodes.h" +#include "bcm_ulog.h" + + + + + +#ifndef DESKTOP_LINUX + +// NOTE: there is another copy of this function in ethswctl_api.c. Need to keep these copies in sync. +// TODO: Delete this copy in 5.04L.03. +static SINT32 ethswctl_init(struct ifreq *ifr) +{ + SINT32 skfd; + + /* Open a basic socket */ + if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + bcmuLog_error("Error openning socket for getting the LAN Only enet port list"); + return -1; + } + + /* Get the name -> if_index mapping for ethswctl */ + memset((void *) ifr, 0, sizeof(*ifr)); + strcpy(ifr->ifr_name, "bcmsw"); + if (ioctl(skfd, SIOCGIFINDEX, ifr) < 0) + { + strcpy(ifr->ifr_name, "eth0"); + if (ioctl(skfd, SIOCGIFINDEX, ifr) < 0) + { + close(skfd); + bcmuLog_error("bcmsw/eth0 interface does not exist. Error: %d", errno); + return -1; + } + } + return skfd; +} + +#ifndef MAX_SYS_ETH_PORT +#define MAX_SYS_ETH_PORT 64 +#endif + +// NOTE: there is another copy of this function in ethswctl_api.c. Need to keep these copies in sync. +// TODO: Delete this copy in 5.04L.03. +static BcmRet getWanLanAttrList(char **nameList, int opcode) +{ + SINT32 skfd; + struct ifreq ifr; + struct ifreq_ext ifx; + + memset((void *) &ifr, 0, sizeof(ifr)); + memset((void *) &ifx, 0, sizeof(ifx)); + + if ((skfd = ethswctl_init(&ifr)) < 0) + { + bcmuLog_error("Error openning socket for getting the opcode 0x%x", opcode); + return BCMRET_INTERNAL_ERROR; + } + + /* Allocate dynamic memory to hold max interface names (eth0,eth1,..eth10)*/ + ifx.bufLen = (MAX_SYS_ETH_PORT * (IFNAMSIZ + 1)) + 2; + if ((*nameList = calloc(1, ifx.bufLen)) == NULL) + { + bcmuLog_error("Fail to alloc mem (%d bytes) for opcode 0x%x", ifx.bufLen, opcode); + close(skfd); + return BCMRET_RESOURCE_EXCEEDED; + } + + ifx.stringBuf = *nameList; + ifx.opcode = opcode; + ifr.ifr_data = (void *)&ifx; + if (ioctl(skfd, SIOCIFREQ_EXT, &ifr) < 0) + { + bcmuLog_error("SIOCIFREQ_EXT opcode=0x%x failed, errno=%d", opcode, errno); + close(skfd); + free(*nameList); + return BCMRET_INTERNAL_ERROR; + } + + close(skfd); + + bcmuLog_debug("Opcode: 0x%x, WAN/LAN If list=%s, strlen=%d", opcode, *nameList, strlen(*nameList)); + + return BCMRET_SUCCESS; +} +#endif + + +BcmRet ethswUtil_getLANOnlyEthPortIfNameList(char **LANOnlyEthPortIfNameList) +{ +#ifdef DESKTOP_LINUX + *LANOnlyEthPortIfNameList = malloc(512); + strcpy(*LANOnlyEthPortIfNameList, "eth4"); + return BCMRET_SUCCESS; +#else + return getWanLanAttrList(LANOnlyEthPortIfNameList, SIOCGPORTLANONLY); +#endif +} + + +BcmRet ethswUtil_getWANOnlyEthPortIfNameList(char **WANOnlyEthPortIfNameList) +{ +#ifdef DESKTOP_LINUX + *WANOnlyEthPortIfNameList = malloc(512); + strcpy(*WANOnlyEthPortIfNameList, "eth0"); + return BCMRET_SUCCESS; +#else + return getWanLanAttrList(WANOnlyEthPortIfNameList, SIOCGPORTWANONLY); +#endif +} + + +BcmRet ethswUtil_getLanWanPortIfNameList(char **LanWanPortIfNameList) +{ +#ifdef DESKTOP_LINUX + *LanWanPortIfNameList = malloc(512); + strcpy(*LanWanPortIfNameList, "eth1,eth3"); + return BCMRET_SUCCESS; +#else + return getWanLanAttrList(LanWanPortIfNameList, SIOCGPORTWANPREFERRED); +#endif +} + + +static UINT32 getPortListCountByPrefix(const char *ifNameList, + const char *prefix, UINT32 prefixLen) +{ + char *tmpList; + char *curIfName; + char *ptr; + char *savePtr = NULL; + UINT32 count = 0; + + tmpList = strdup(ifNameList); + if (!tmpList) + { + bcmuLog_error("Memory allocation failure"); + return 0; + } + + ptr = strtok_r(tmpList, ",", &savePtr); + + while (ptr) + { + curIfName = ptr; + while ((isspace((UINT8)*curIfName)) && (*curIfName != 0)) + { + /* Skip possible white space after comma. */ + curIfName++; + } + + if ((prefix == NULL) || + ((prefix != NULL) && (!strncmp(curIfName, prefix, prefixLen)))) + { + count++; + } + ptr = strtok_r(NULL, ",", &savePtr); + } + + free(tmpList); + return count; +} + + +BcmRet ethswUtil_getLANOnlyEthPortNumByPrefix(const char *prefix __attribute__((unused)), + UINT32 prefixLen __attribute__((unused)), UINT32 *numP) +{ + char *pLANOnlyPortList = NULL; + BcmRet ret = BCMRET_SUCCESS; + +#ifdef DESKTOP_LINUX + pLANOnlyPortList = malloc(512); + strcpy(pLANOnlyPortList, "eth2,eth4"); + *numP = getPortListCountByPrefix(pLANOnlyPortList, NULL, 0); + free(pLANOnlyPortList); +#else + ret = ethswUtil_getLANOnlyEthPortIfNameList(&pLANOnlyPortList); + *numP = getPortListCountByPrefix(pLANOnlyPortList, prefix, prefixLen); + bcmuLog_debug("LAN only: %s, number: %d\n", pLANOnlyPortList, *numP); + free(pLANOnlyPortList); +#endif + + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ethswutils.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ethswutils.h new file mode 100644 index 00000000000..1418e4b3b7e --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ethswutils.h @@ -0,0 +1,108 @@ +/*********************************************************************** + * + * Copyright (c) 2020 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2020:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + + +#ifndef __BCM_ETHSWUTIL_H__ +#define __BCM_ETHSWUTIL_H__ + +/*!\file bcm_ethswutil.h + * \brief Header file for BCM ethsw util functions. + * + */ + +#include "bcm_retcodes.h" +#include "number_defs.h" + + + +/** Get a list of LAN Only Eth interface names in the system. + * This function is deprecated, call bcm_enet_driver_getLANOnlyEthPortIfNameList() instead. + * TODO: Delete in 5.04L.03. + * + * @param LANOnlyEthPortIfNameList (OUT) Pointer to char * of pLANOnlyPortList. + * This function will malloc() a buffer big enough to hold a list + * of all the LAN interface names in the system, separated by comma. + e.g. eth0,eth1 + * Caller is responsible for freeing the buffer with free(), NOT + * cmsMem_free + * + * @return BcmRet code. + */ +BcmRet ethswUtil_getLANOnlyEthPortIfNameList(char **LANOnlyEthPortIfNameList); + + +/** Get a list of WAN Only Eth interface names in the system. + * This function is deprecated, call bcm_enet_drivergetWANOnlyEthPortIfNameList() instead. + * TODO: Delete in 5.04L.03. + * + * @param WANOnlyEthPortIfNameList (OUT) Pointer to char * of pWANOnlyPortList. + * This function will malloc() a buffer big enough to hold a list + * of all WAN the interface names in the system, separated by comma. + * e.g. eth0,eth1 + * Caller is responsible for freeing the buffer with free(), NOT + * cmsMem_free + * + * @return BcmRet code. + */ +BcmRet ethswUtil_getWANOnlyEthPortIfNameList(char **WANOnlyEthPortIfNameList); + + +/** Get a list of Eth interfaces names in the system, a port in this list can + * be configured as either LAN or WAN. + * This function is deprecated, call bcm_enet_driver_getLanWanPortIfNameList() instead. + * TODO: Delete in 5.04L.03. + * + * @param LanWanPortIfNameList (OUT) Pointer to char * of pLanWanPortIfNameList. + * This function will malloc() a buffer big enough to hold a list + * of all the interface names in the system, separated by comma. + * e.g. eth0,eth1 + * Caller is responsible for freeing the buffer with free(), NOT + * cmsMem_free + * + * @return BcmRet code. + */ +BcmRet ethswUtil_getLanWanPortIfNameList(char **LanWanPortIfNameList); + + +/** Get number of LAN Only Eth interface names in the system. + * + * @param prefix (IN) interface prefix or NULL. + * @param prefixLen (IN) interface prefix length if applicable. + * @param numP (OUT) Pointer to the counter. + * + * @return BcmRet code. + */ +BcmRet ethswUtil_getLANOnlyEthPortNumByPrefix(const char *prefix, + UINT32 prefixLen, UINT32 *numP); + + + +#endif /* __BCM_ETHSWUTIL_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_fsutils.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_fsutils.c new file mode 100644 index 00000000000..932249c31d1 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_fsutils.c @@ -0,0 +1,172 @@ +/*********************************************************************** + * + * Copyright (c) 2019 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2018:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "bcm_fsutils.h" +#include "bcm_ulog.h" +#include "sysutil_fs.h" + +#include "cms_params.h" // for SMD_SHUTDOWN_IN_PROGRESS + + +BcmRet bcmUtl_getBaseDir(char *pathBuf, UINT32 pathBufLen) +{ + UINT32 rc; + +#if defined(DESKTOP_LINUX) + char pwd[1024]={0}; + UINT32 pwdLen = sizeof(pwd); + char *str; + char *envDir; + struct stat statbuf; + + /* + * If user has set an env var to tell us where the base dir is, + * always use it. + */ + if ((envDir = getenv("SDK_BASE_DIR")) != NULL) + { + rc = snprintf(pwd, sizeof(pwd), "%s/userspace", envDir); + if (rc >= (SINT32) sizeof(pwd)) + { + bcmuLog_error("env var %s too long (max=%d)", envDir, sizeof(pwd)); + return BCMRET_RESOURCE_EXCEEDED; + } + if ((rc = stat(pwd, &statbuf)) == 0) + { + /* SDK_BASE_DIR is good, use it. */ + rc = snprintf(pathBuf, pathBufLen, "%s", envDir); + } + else + { + /* SDK_BASE_DIR is set, but points to bad location */ + return BCMRET_INVALID_ARGUMENTS; + } + } + else + { + /* + * User did not set env var, so try to figure out where base dir is + * based on current directory. + */ + if (NULL == getcwd(pwd, pwdLen) || + strlen(pwd) == pwdLen - 1) + { + bcmuLog_error("Buffer for getcwd is not big enough"); + return BCMRET_INTERNAL_ERROR; + } + + str = strstr(pwd, "userspace"); + if (str == NULL) + { + str = strstr(pwd, "unittests"); + } + if (str != NULL) + { + /* + * OK, we are running from under a recognized top level directory + * (userspace or unittests). + * null terminate the string right before that directory and that + * should give us the basedir. + */ + str--; + *str = 0; + + rc = snprintf(pathBuf, pathBufLen, "%s", pwd); + } + else + { + // Can't figure out our base dir. + return BCMRET_INVALID_ARGUMENTS; + } + } + +#elif defined(BUILD_DESKTOP_BEEP) + + rc = snprintf(pathBuf, pathBufLen, "/var"); + +#else + + // Normal system build. + rc = snprintf(pathBuf, pathBufLen, "/"); + +#endif /* DESKTOP_LINUX or BUILD_DESKTOP_BEEP */ + + if (rc >= pathBufLen) + { + bcmuLog_error("pathBufLen %d is too small for buf %s", pathBufLen, pathBuf); + return BCMRET_RESOURCE_EXCEEDED; + } + + return BCMRET_SUCCESS; +} + + +void bcmUtl_declareShutdownInProgress(const char *requestingApp) +{ + const char *unknown="unknown"; + BcmRet ret = BCMRET_INTERNAL_ERROR; + + if (requestingApp != NULL) + { + printf("%s is about to shut system down...", requestingApp); + ret = sysUtil_writeBufferToFile(SMD_SHUTDOWN_IN_PROGRESS, + (UINT8 *) requestingApp, strlen(requestingApp)); + } + else + { + printf("unknown app is about to shut system down..."); + ret = sysUtil_writeBufferToFile(SMD_SHUTDOWN_IN_PROGRESS, + (UINT8 *) unknown, strlen(unknown)); + } + fflush(stdout); + + if (ret != BCMRET_SUCCESS) + { + bcmuLog_error("write of %s failed, ret=%d", + SMD_SHUTDOWN_IN_PROGRESS, ret); + } + + return; +} + + +int bcmUtl_isShutdownInProgress() +{ + return (sysUtil_isFilePresent(SMD_SHUTDOWN_IN_PROGRESS)); +} + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_fsutils.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_fsutils.h new file mode 100644 index 00000000000..e7554e3c445 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_fsutils.h @@ -0,0 +1,79 @@ +/*********************************************************************** + * + * Copyright (c) 2019 Broadcom Ltd + * All Rights Reserved + * + * <:label-BRCM:2018:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * +************************************************************************/ + +#ifndef __BCM_FSUTILS_H__ +#define __BCM_FSUTILS_H__ + +#include "number_defs.h" +#include "bcm_retcodes.h" + +#if defined __cplusplus +extern "C" { +#endif + +/*!\file bcm_fsutils.h + * \brief Broadcom filesystem helper functions. + * + * This file contains Broadcom specific filesystem operations. + * Generic file system operations should go into the sys_util lib. + */ + +/** Return the path to the CommEngine build directory in the given buffer. + * + * This function should only be used in the DESKTOP_LINUX mode, but if + * it is called on a real gateway build, it will return /. + * + * @param pathBuf (OUT) Contains the pathBuf. + * @param pathBufLen (IN) Length of the buffer. If the buffer is not large + * enough to hold the path, an error will be returned. + * @return CmsRet enum. + */ +BcmRet bcmUtl_getBaseDir(char *pathBuf, UINT32 pathBufLen); + + +/** Write a hint file in tmp filesystem to indicate shutdown is in progress. + * This allows apps to exit silently instead of printing an error if it + * loses connection to some other app. Note this function does NOT actually + * shut down the system. The calling app needs to do that separately. + * + * @param requestingApp (IN) provide the string name of the app declaring + * the shutdown. + */ +void bcmUtl_declareShutdownInProgress(const char *requestingApp); + +/** Return 1 if shutdown is in progress (hint file present), else return 0. */ +int bcmUtl_isShutdownInProgress(); + + +#if defined __cplusplus +}; +#endif +#endif /* __BCM_FSUTILS_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_net.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_net.c new file mode 100644 index 00000000000..e1359676abd --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_net.c @@ -0,0 +1,310 @@ +/*********************************************************************** + * + * Copyright (c) 2019 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2018:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + +#include +#include +#include +#include + +#include "bcm_ulog.h" + + +/* The returned data from the command 'pspctl dump WanRate' has + the format of XXYY, where XX represents the downstream rate and + YY represents the upstream rate. If XX or YY is equal to 25, it + means that data rate is 2.5G. If XX or YY is equal to 10 or 1, + it translates to 10G or 1G, respectively. This function takes + the "XX" or "YY" as an input string and returns the corresponding + data rate in kbps */ +static inline int __resolveVeipSpeed(char *buf) +{ + int tmpSpeed = atoi(buf); + if (tmpSpeed == 25) + tmpSpeed = 2500000; + else + tmpSpeed = tmpSpeed * 1000000; + return tmpSpeed; +} + + +/* This function determines the local interface that could reach to the given + server IP address and the data rate (in kbps) at which the gateway can + transmit (and receive) to (and from) the given server IP. */ +int bcmNet_getRouteInfoToServer(const char *serverIp, char* intfName, + char *intfIp, int *upSpeed, int *downSpeed) +{ + char buf[512], *bufp, cmd[128] = {0}, tmp[32], macAddr[18] = {0}; + FILE *p = NULL; + int ret = 0, portNumber = -1; + unsigned long int tmpSpeed = 0; + + /* get the local interface that can reach to the given server IP */ + snprintf(buf, sizeof(buf), "/bin/ip route get %s", serverIp); + p = popen(buf, "r"); + if ((NULL == p) || (NULL == fgets(buf, 512, p))) + { + bcmuLog_notice("Failed to get local interface that can reach %s", serverIp); + ret = -1; + } + if (p) + pclose(p); + if (ret != -1) + { + bufp = strstr(buf, "dev"); + if (bufp) + sscanf(bufp + strlen("dev"), " %s", intfName); + + bufp = strstr(buf, "src"); + if (bufp) + sscanf(bufp + strlen("src"), " %s", intfIp); + } + + if (strstr(intfName, "br") != NULL) + { + /* The interface that can reach the given server is through the bridge! + Determine the port on the bridge that could reach the server by doing + the steps below: */ + /* Step 1. ping the server IP once */ + snprintf(buf, sizeof(buf), "/bin/ping %s -c 1", serverIp); + p = popen(buf, "r"); + if (p) + pclose(p); + + /* Step 2. look up the arp table for the mac address of the corresponding IP */ + snprintf(cmd, sizeof(cmd), "/bin/ip neighbour | grep %s", serverIp); + p = popen(cmd, "r"); + if ((NULL == p) || (EOF == fscanf(p, "%s %s %s %s %s", tmp, tmp, tmp, tmp, macAddr))) + { + bcmuLog_notice("Failed to get mac address of the server from the arp table\n"); + ret = -1; + } + if (p) + pclose(p); + + /* Step 3. find the port number in the bridge that saw the mac address of the server. */ + if (strlen(macAddr)) { + + /* try brctl to find the port number in the bridge */ + snprintf(cmd, sizeof(cmd), "/bin/brctl showmacs %s 2>/dev/null | grep %s", intfName, macAddr); + p = popen(cmd, "r"); + if ((NULL == p) || (EOF == fscanf(p, "%d", &portNumber))) + { + bcmuLog_notice("Failed to get port number using brctl on the bridge that can reach %s\n", serverIp); + if (p) + pclose(p); + + /* try ovs-appctl to find the port number in the bridge */ + snprintf(cmd, sizeof(cmd), "/bin/ovs-appctl fdb/show %s 2>/dev/null | grep %s", intfName, macAddr); + p = popen(cmd, "r"); + if ((NULL == p) || (EOF == fscanf(p, "%d", &portNumber))) + { + bcmuLog_notice("Failed to get port number using ovs-appctl on the bridge that can reach %s\n", serverIp); + ret = -1; + } + } + if (p) + pclose(p); + } + + /* Step 4. Map the port number in the bridge table back to the interface name. */ + if (portNumber >= 0) { + + /* try brctl to map the port number back to the interface name */ + snprintf(cmd, sizeof(cmd), "/bin/brctl showstp %s 2>/dev/null | grep '(%d)'", intfName, portNumber); + p = popen(cmd, "r"); + if ((NULL == p) || (EOF == fscanf(p, "%s", intfName))) + { + bcmuLog_notice("Failed to get the interface name associated to the port on the bridge using brctl\n"); + if (p) + pclose(p); + + /* try to use ovs-ofctl to map the port number back to the interface name */ + snprintf(cmd, sizeof(cmd), "/bin/ovs-ofctl show %s 2>/dev/null | grep '%d('", intfName, portNumber); + p = popen(cmd, "r"); + if ((NULL == p) || (EOF == fscanf(p, " %d(%[^)])", &portNumber, intfName))) + { + bcmuLog_notice("Failed to get the interface name associated to the port on the bridge using ovs-ofctl\n"); + ret = -1; + } + } + if (p) + pclose(p); + } + bcmuLog_notice("%s %s %d\n", intfName, macAddr, portNumber); + } + + + if (strstr(intfName, "eth") != NULL) { + *upSpeed = 1000; /* set speed to 1G if nothing works out */ + snprintf(cmd, sizeof(cmd), "/sys/class/net/%s/speed", intfName); + p = fopen(cmd, "r"); + if ((NULL == p) || (EOF == fscanf(p, "%d", upSpeed))) + { + bcmuLog_notice("Failed to get speed for %s\n", intfName); + ret = -1; + } + if (p) + fclose(p); + *downSpeed = *upSpeed = *upSpeed * 1000; + } + else if (strstr(intfName, "ptm") != NULL || strstr(intfName, "atm") != NULL) + { + int currUpSpeed = 0, currDownSpeed = 0; + *upSpeed = *downSpeed = 0; + + p = popen("/bin/xtm datapath --status", "r"); + if (NULL != p) + { + while (fgets(buf, sizeof(buf), p)) + { + printf("%s", buf); + bufp = strstr(buf, "US Rate"); + if (bufp) { + bufp = strstr(bufp, "="); + if (EOF != sscanf(bufp, "= %lu bps", &tmpSpeed)) { + currUpSpeed = tmpSpeed/1000; + } else { + bcmuLog_notice("Failed to get US rate for %s\n", intfName); + ret = -1; + } + } + bufp = strstr(buf, "DS Rate"); + if (bufp) { + bufp = strstr(bufp, "="); + if (EOF != sscanf(bufp, "= %lu bps", &tmpSpeed)) { + currDownSpeed = tmpSpeed/1000; + } else { + bcmuLog_notice("Failed to get DS rate for %s\n", intfName); + ret = -1; + } + } + if (*upSpeed < currUpSpeed) + *upSpeed = currUpSpeed; + if (*downSpeed < currDownSpeed) + *downSpeed = currDownSpeed; + } + pclose(p); + /* set speed to 1G if nothing works out */ + if (!*upSpeed) + *upSpeed = 1000000; + if (!*downSpeed) + *downSpeed = 1000000; + } + else + { + bcmuLog_notice("Failed to get speed for %s\n", intfName); + ret = -1; + } + } + else if (strstr(intfName, "veip") != NULL) + { + *upSpeed = *downSpeed = 1000000; /* set speed to 1G if nothing works out */ + p = popen("/bin/pspctl dump WanRate", "r"); + if ((NULL == p) || (EOF == fscanf(p, "%s", buf))) + { + bcmuLog_notice("Failed to get speed for %s\n", intfName); + ret = -1; + } + else + { + *upSpeed = __resolveVeipSpeed(buf+2); + buf[2] = '\0'; + *downSpeed = __resolveVeipSpeed(buf); + } + if (p) + pclose(p); + + } + else + { + *upSpeed = *downSpeed = 1000000; /* set speed to 1G if nothing works out */ + } + bcmuLog_notice("Route info for %s: SrcIntf=%s SrcIP=%s upSpeed=%d downSpeed=%d\n", + serverIp, intfName, intfIp, *upSpeed, *downSpeed); + + return ret; +} + +/* This function gets the uboot ipaddr/netmask environment parameters. + * If the netmaks isn't specified, it will assigned it accordingly. + * e.g. 192.168.1.x->255.255.255.0; 10.x.x.x->255.0.0.0; 172.x->255.240.0.0; others->255.255.0.0 + * If failed to get the values from uboot, it assigned the default setting which is + * 192.168.1.1/255.255.255.0 + */ +void bcmNet_getDefaultLanIpInfo(char *ipaddr, int iplen, char* netmask, int masklen) +{ + FILE* fs; + /* Try to use the ipaddress/netmask from uboot environment parameters */ + fs = fopen("/proc/environment/ipaddr", "r"); + if ( fs != NULL ) { + if ( fgets(ipaddr, iplen, fs) != NULL ) + bcmuLog_notice("Failed to get ipaddr."); + fclose(fs); +#if 0 //TODO: move cmsUtl_isValidIpv4Address to bcmUtl. + if ( ! cmsUtl_isValidIpv4Address(ipaddr)) + { + snprintf(ipaddr, iplen, "%s", "192.168.1.1"); + } +#endif + } + else + { + snprintf(ipaddr, iplen, "%s", "192.168.1.1"); + } + fs = fopen("/proc/environment/netmask", "r"); + if ( fs != NULL ) { + if ( fgets(netmask, masklen, fs) != NULL ) + bcmuLog_notice("Failed to get netmask."); + fclose(fs); +#if 0 //TODO: move cmsUtl_isValidIpv4Address to bcmUtl. + if ( ! cmsUtl_isValidIpv4Address(netmask)) + { + snprintf(netmask, masklen, "%s", "255.255.255.0"); + } +#endif + } + else + { + if ( !strncmp(ipaddr, "10.", strlen("10."))) + { + snprintf(netmask, masklen, "%s", "255.0.0.0"); + } + else if ( !strncmp(ipaddr, "172.16.", strlen("172.16."))) + { + snprintf(netmask, masklen, "%s", "255.255.0.0"); + } + else + { + snprintf(netmask, masklen, "%s", "255.255.255.0"); + } + } + return; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_net.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_net.h new file mode 100644 index 00000000000..06ddb5e49a5 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_net.h @@ -0,0 +1,82 @@ +/*********************************************************************** + * + * Copyright (c) 2019 Broadcom Ltd + * All Rights Reserved + * + * <:label-BRCM:2018:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * +************************************************************************/ + +#ifndef __BCM_NET_H__ +#define __BCM_NET_H__ + +#if defined __cplusplus +extern "C" { +#endif + +/*!\file bcm_net.h + * \brief Broadcom Userspace Network helper utility. + * + * This utility leverages on Linux's networking/routing tools to help + * retrieving networking and routing information of the system. + */ + + +/** Retrieve the local interface (and its properties) that the system + * can use to reach the given server. + * + * This function returns the name and IP address of the local interface that + * the system can use to reach the given server IP address. In addition, + * the maximum data rates at which the gateway can transmit/receive to/from + * the given server IP addresses at the determined local interface are also + * returned. + * + * @param serverIp (IN) destination server IP in dotted decimal format + * (IPv4 or IPv6) + * @param intfName (OUT) outbound interface name to use. The buffer must be + * at least IFNAMSZ (16 bytes as defined in net/if.h) + * @param intfIp (OUT) outbound interface IP in dotted decimal format. The + * buffer must be at least INET_ADDRSTRLEN (16 bytes) for IPv4, or + * INET6_ADDRSTRLEN (46 bytes) for IPv6 + * @param upSpeed (OUT) the uplink speed in kbps + * @param downSpeed (OUT) the downlink speed kbps + * @return 0 on success, -1 on error +*/ +int bcmNet_getRouteInfoToServer(const char *serverIp, char* intfName, + char *intfIp, int *upSpeed, int *downSpeed); + + +/* This function gets the uboot ipaddr/netmask environment parameters. + * If the netmaks isn't specified, it will assigned it accordingly. + * e.g. 192.168.1.x->255.255.255.0; 10.x.x.x->255.0.0.0; 172.x->255.240.0.0; others->255.255.0.0 + * If failed to get the values from uboot, it assigned the default setting which is + * 192.168.1.1/255.255.255.0 + */ +void bcmNet_getDefaultLanIpInfo(char *ipaddr, int iplen, char* netmask, int masklen); + +#if defined __cplusplus +}; +#endif +#endif /* __BCM_NET_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_strutils.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_strutils.c new file mode 100644 index 00000000000..0978e47236a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_strutils.c @@ -0,0 +1,98 @@ +/*********************************************************************** + * + * Copyright (c) 2021 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2021:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "bcm_strutils.h" + +// Comment this out if strsep() is not available, then we will use the +// Broadcom implementation. +#define USE_STRSEP + +char *bcmUtl_strtok_r(char *str, const char *delim, char **saveptr) +{ +#ifdef USE_STRSEP + // strsep() seems to do what we need, but could be less portable. + // does musl and ucLibc have it? + if (str != NULL) + { + *saveptr = str; + } + return (strsep(saveptr, delim)); +#else + // This is the Broadcom implementation. + char *token, *ptr; + + // Check delim char + if ((delim == NULL) || (delim[0] == '\0') || (delim[1] != '\0')) + { + // delim must be a single character. + return NULL; + } + + if (saveptr == NULL) // savePtr always required + return NULL; + + if ((str != NULL) && (*saveptr != NULL)) // can't specify both + return NULL; + + token = (str != NULL) ? str : *saveptr; + if (token == NULL) + { + // No more data to parse. + *saveptr = NULL; + return NULL; + } + + ptr = token; + while ((*ptr != delim[0]) && (*ptr != '\0')) + ptr++; + + if (*ptr == delim[0]) + { + // we hit a delimiter, terminate token by overwriting delim with NULL + *ptr = '\0'; + *saveptr = ptr+1; // next call, start at next token. + } + else + { + // we hit end of string, no more data on next call. + *saveptr = NULL; + } + + return token; +#endif /* USE_STRSEP */ +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_strutils.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_strutils.h new file mode 100644 index 00000000000..9e6daf6c28d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_strutils.h @@ -0,0 +1,71 @@ +/*********************************************************************** + * + * Copyright (c) 2021 Broadcom Ltd + * All Rights Reserved + * + * <:label-BRCM:2021:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * +************************************************************************/ + +#ifndef __BCM_STRUTILS_H__ +#define __BCM_STRUTILS_H__ + +#include + + + +/*!\file bcm_strutils.h + * \brief Broadcom string helper functions. Similar to CMS strconv but + * not tied to CMS. + * + */ + +#if defined __cplusplus +extern "C" { +#endif + +/** By default, this is just a wrapper around strsep(). + * + * In case strsep is not available, there is a Broadccom implementation which + * behaves just like standard strtok_r with 3 exceptions: + * + * 1. contiguous delimitors are NOT treated like a single delimitor. Two + * contiguous delimitors is treated as if there is an empty string value + * between the two delimitors. Returned char *ptr == '\0'. + * 2. Delimitors must be only a single character. Multiple delimitors not + * supported. + * 3. If there is no more data to parse, *savePtr will be NULL on exit. + * + * See man page for strtok_r for behavior. + * + * @return ptr to token, or NULL if no more tokens or error. + */ +char *bcmUtl_strtok_r(char *str, const char *delim, char **saveptr); + + +#if defined __cplusplus +}; +#endif +#endif /* __BCM_STRUTILS_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_timestamp.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_timestamp.c new file mode 100644 index 00000000000..bf9fa5fd721 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_timestamp.c @@ -0,0 +1,70 @@ +/*********************************************************************** + * + * Copyright (c) 2020 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2020:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + +#include +#include +#include + +static int timestamp_initialized = 0; +static int (*_bcm_clock_gettime_fn) (clockid_t, struct timespec *); + +/* Work around to avoid glibc symbols being hijacked by libshared.so, which is + * a library in wifi userspace code. The correct way would be modify wifi code + * to remove those redefinition of glibc functions. Until that happens, we use + * dlsym to force symbol resole to glibc. + */ +int bcm_libc_clock_gettime(clockid_t clkid, struct timespec *ts) +{ + if (timestamp_initialized == 0) + { + void *handle, *p; + + handle = dlopen ("libc.so.6", RTLD_LAZY); + if (handle != NULL) + { + p = dlsym(handle, "clock_gettime"); + if (p != NULL) + { + _bcm_clock_gettime_fn = p; + } + } + timestamp_initialized = 1; + } + + if (_bcm_clock_gettime_fn != NULL) + { + return (*_bcm_clock_gettime_fn)(clkid, ts); + } + else + { + return clock_gettime(clkid, ts); + } +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_timestamp.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_timestamp.h new file mode 100644 index 00000000000..70153f3356d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_timestamp.h @@ -0,0 +1,43 @@ +/*********************************************************************** + * + * Copyright (c) 2020 Broadcom Ltd + * All Rights Reserved + * + * <:label-BRCM:2020:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * +************************************************************************/ +#ifndef __BCM_TIMESTAMP_H__ +#define __BCM_TIMESTAMP_H__ + +#if defined __cplusplus +extern "C" { +#endif + +int bcm_libc_clock_gettime(clockid_t, struct timespec *); + +#if defined __cplusplus +}; +#endif +#endif /* __BCM_TIMESTAMP_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ulog.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ulog.c new file mode 100644 index 00000000000..48a6cc02996 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ulog.c @@ -0,0 +1,601 @@ +/*********************************************************************** + * + * Copyright (c) 2018 Broadcom Ltd + * All Rights Reserved + * +<:label-BRCM:2018:DUAL/GPL:standard + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sysutil.h" +#include "sysutil_proc.h" +#include "bcm_ulog.h" +#include "bcm_timestamp.h" + + +/** These variables are now used by CMS Log as well. They are not static, + * but don't advertise their visibility in the header file either. Normal + * callers should still use APIs to get/set them. + * uLogLevel, ulogDestMask, ulogHdrMask, ulogAppName will apply to all threads + * in a multi-threaded application unless a thread-specific value has been + * set via setLevelEx, setDestMaskEx, setHdrMaskEx, or setNameEx. + */ +BcmuLogLevel ulogLevel = BCMULOG_DEFAULT_LEVEL; +UINT32 ulogDestMask = BCMULOG_DEFAULT_DESTMASK; +UINT32 ulogHdrMask = BCMULOG_DEFAULT_HDRMASK; +char ulogAppName[BCMULOG_MAX_APP_NAME_LEN] = {0}; + +// For performance tracing messages (for all threads) +UINT32 uTraceDestMask = BCMULOG_DESTMASK_SYSLOG; + + +// These are per-thread level, destMask, hdrMask, and appName settings. +// According to StackOverflow (C89 standard), global vars are automatically +// initialized to 0. But I still like to initialize them if possible. +BcmuLogThreadInfo ulogLevelArray[BCMULOG_NUM_THREAD_SLOTS]; +UINT32 ulogLevelEntries = 0; + +BcmuLogThreadInfo ulogDestMaskArray[BCMULOG_NUM_THREAD_SLOTS]; +UINT32 ulogDestMaskEntries = 0; + +BcmuLogThreadInfo ulogHdrMaskArray[BCMULOG_NUM_THREAD_SLOTS]; +UINT32 ulogHdrMaskEntries = 0; + +BcmuLogThreadInfo ulogAppNameArray[BCMULOG_NUM_THREAD_SLOTS]; +UINT32 ulogAppNameEntries = 0; + +// EID to threadId mapping table. +BcmuLogThreadInfo ulogEidToThreadIdArray[BCMULOG_NUM_THREAD_SLOTS]; +UINT32 ulogEidToThreadIdEntries = 0; + + +static UINT32 getMyValueCommon(const BcmuLogThreadInfo *array, const char *arrayName, + UINT32 numSlots, UINT32 numEntries, + SINT32 threadId, UINT32 eid, + UINT32 globalValue) +{ + UINT32 i; + + if (threadId == 0 && eid != 0) + { + threadId = bcmuLog_getEidToThreadId(eid); + } + + if (threadId == 0) + { + bcmuLog_debug("table %s: unknown threadId (eid=%d) returning app-wide value 0x%x", + arrayName, eid, globalValue); + return globalValue; + } + + // Most common case: no per thread info, just return the app-wide setting. + if (numEntries == 0) + return globalValue; + + for (i=0; i < numSlots; i++) + { + if (array[i].threadId == threadId) + return (array[i].value); + } + + // setting for this thread not found, return app-wide setting. + return globalValue; +} + +static void setValueNameCommon(BcmuLogThreadInfo *array, const char *arrayName, + UINT32 numSlots, UINT32 *numEntries, + SINT32 threadId, UINT32 eid, + const char *name, UINT32 value) +{ + UINT32 i; + + if (threadId != 0 && eid != 0) + { + // both are specified, so we can fill in the mapping entry. + bcmuLog_setEidToThreadId(eid, threadId); + } + + if (threadId == 0 && eid != 0) + { + threadId = bcmuLog_getEidToThreadId(eid); + } + + if (threadId == 0) + { + bcmuLog_error("table %s: unknown threadId %d (eid=%d)", + arrayName, threadId, eid); + return; + } + + // At this point, we have a valid threadId. + // First check for modification to existing entry. + for (i=0; i < numSlots; i++) + { + if (array[i].threadId == threadId) + { + if (name != NULL) + { + strncpy(array[i].appName, name, sizeof(array[i].appName)-1); + } + else + { + array[i].value = value; + } + return; + } + } + + // New threadId setting, try to find an empty slot. + // TODO: add locking? Technically, it is possible that two threads will + // find the same slot free and try to fill it. But in practice, very few + // threads will set their per-thread info, and usually only once right at + // startup, so it is extremely unlikely we will have a collision/overwrite. + for (i=0; i < numSlots; i++) + { + if (array[i].threadId == 0) + { + array[i].threadId = threadId; + if (name != NULL) + { + strncpy(array[i].appName, name, sizeof(array[i].appName)-1); + } + else + { + array[i].value = value; + } + (*numEntries)++; + return; + } + } + + // No more empty slots. + // TODO: there is no mechanism to clear a slot after it has been set. + // Assuming all of these threads are long-lived. + bcmuLog_error("BCM ULog (%s) thread table full (max=%d)", + arrayName, numSlots); + return; +} + + +void bcmuLog_formatInfo(FILE *stream, BcmuLogFormatInfo *info) +{ + if (info->logHeaderMask & BCMULOG_HDRMASK_APPNAME) + { + if (info->appName[0] != '\0') + { + fprintf(stream, "%s", info->appName); + } + } + fprintf(stream, ":"); + + if (info->logHeaderMask & BCMULOG_HDRMASK_THREAD_ID) + { + int tid = sysUtl_gettid(); + fprintf(stream, "%d", tid); + } + fprintf(stream, ":"); + + /* + * Eventhough syslog will also log the time, this timestamp is more accurate. + * But caller can always turn it off. + */ + if (info->logHeaderMask & BCMULOG_HDRMASK_TIMESTAMP) + { + struct timespec ts = {0, 0}; + bcm_libc_clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stream, "%lu.%03lu", ts.tv_sec%1000, ts.tv_nsec/1000000); + } + fprintf(stream, ":"); + + if (info->logHeaderMask & BCMULOG_HDRMASK_LEVEL) + { + /* + * Don't include severity when going to syslog because syslog puts + * that in for us. + */ + if (!(info->logDestMask & BCMULOG_DESTMASK_SYSLOG)) + { + char *logLevelStr; + switch(info->logLevel) + { + case BCMULOG_LEVEL_ERR: + logLevelStr = "error"; + break; + case BCMULOG_LEVEL_NOTICE: + logLevelStr = "notice"; + break; + case BCMULOG_LEVEL_DEBUG: + logLevelStr = "debug"; + break; + case BCMULOG_LEVEL_PERFTRACE: + logLevelStr = "trace"; + break; + default: + logLevelStr = "invalid-log-level"; + break; + } + fprintf(stream, "%s", logLevelStr); + } + } + fprintf(stream, ":"); + + if (info->logHeaderMask & BCMULOG_HDRMASK_LOCATION) + { + fprintf(stream, "%s:%u", info->funcName, info->lineNum); + } + fprintf(stream, ":"); +} + +void bcmuLog_formatLine(FILE *stream, BcmuLogFormatInfo *info, const char *pFmt, va_list ap) +{ + bcmuLog_formatInfo(stream, info); + + vfprintf(stream, pFmt, ap); +} + +void bcmuLog_formatPerfTrace(FILE *stream, BcmuLogFormatInfo *info, const char *anchor, const char *pFmt, va_list ap) +{ + bcmuLog_formatInfo(stream, info); + fprintf(stream, "%s:", anchor); + vfprintf(stream, pFmt, ap); +} + +void bcmuLog_setLevel(UINT32 level) +{ + ulogLevel = level; +} + +void bcmuLog_setLevelEx(UINT32 level, SINT32 threadId, UINT32 eid) +{ + setValueNameCommon(ulogLevelArray, "level", + BCMULOG_NUM_THREAD_SLOTS, &ulogLevelEntries, + threadId, eid, + NULL, level); + return; +} + +UINT32 bcmuLog_getLevel(void) +{ + return ulogLevel; +} + +UINT32 bcmuLog_getLevelEx(SINT32 threadId, UINT32 eid) +{ + return (getMyValueCommon(ulogLevelArray, "level", + BCMULOG_NUM_THREAD_SLOTS, ulogLevelEntries, + threadId, eid, + (UINT32) ulogLevel)); +} + +void bcmuLog_setHdrMask(UINT32 mask) +{ + ulogHdrMask = mask; +} + +void bcmuLog_setHdrMaskEx(UINT32 mask, SINT32 threadId, UINT32 eid) +{ + setValueNameCommon(ulogHdrMaskArray, "hdrMask", + BCMULOG_NUM_THREAD_SLOTS, &ulogHdrMaskEntries, + threadId, eid, + NULL, mask); + return; +} + +UINT32 bcmuLog_getHdrMask(void) +{ + return ulogHdrMask; +} + +UINT32 bcmuLog_getHdrMaskEx(SINT32 threadId, UINT32 eid) +{ + return (getMyValueCommon(ulogHdrMaskArray, "hdrMask", + BCMULOG_NUM_THREAD_SLOTS, ulogHdrMaskEntries, + threadId, eid, + ulogHdrMask)); +} + +void bcmuLog_setDestMask(UINT32 mask) +{ + ulogDestMask = mask; +} + +void bcmuLog_setDestMaskEx(UINT32 mask, SINT32 threadId, UINT32 eid) +{ + setValueNameCommon(ulogDestMaskArray, "destMask", + BCMULOG_NUM_THREAD_SLOTS, &ulogDestMaskEntries, + threadId, eid, + NULL, mask); + return; +} + +UINT32 bcmuLog_getDestMask() +{ + return ulogDestMask; +} + +UINT32 bcmuLog_getDestMaskEx(SINT32 threadId, UINT32 eid) +{ + return (getMyValueCommon(ulogDestMaskArray, "destMask", + BCMULOG_NUM_THREAD_SLOTS, ulogDestMaskEntries, + threadId, eid, + ulogDestMask)); +} + +void bcmuLog_setName(const char *name) +{ + if (name != NULL) + { + strncpy(ulogAppName, name, sizeof(ulogAppName)-1); + } +} + +void bcmuLog_setNameFromProc() +{ + ProcThreadInfo tInfo; + int tid; + + tid = sysUtl_gettid(); + sysUtl_getThreadInfoFromProc(tid, &tInfo); + strncpy(ulogAppName, tInfo.name, sizeof(ulogAppName)-1); + return; +} + +void bcmuLog_setNameEx(const char *name, SINT32 threadId, UINT32 eid) +{ + if (name != NULL) + { + setValueNameCommon(ulogAppNameArray, "appName", + BCMULOG_NUM_THREAD_SLOTS, &ulogAppNameEntries, + threadId, eid, + name, 0); + } + return; +} + +const char *bcmuLog_getName(void) +{ + if (ulogAppName[0] == '\0') + { + bcmuLog_setNameFromProc(); + } + + return ulogAppName; +} + +const char *bcmuLog_getNameEx(SINT32 threadId, UINT32 eid) +{ + UINT32 i; + + if (ulogAppName[0] == '\0') + { + bcmuLog_setNameFromProc(); + } + + if (threadId == 0 && eid != 0) + { + threadId = bcmuLog_getEidToThreadId(eid); + } + + if (threadId == 0) + { + bcmuLog_debug("table appName: unknown threadId (eid=%d) returning app-wide value %s", + eid, ulogAppName); + return ulogAppName; + } + + // Most common case: no per thread info, just return the app-wide setting. + if (ulogAppNameEntries == 0) + return ulogAppName; + + for (i=0; i < BCMULOG_NUM_THREAD_SLOTS; i++) + { + if (ulogAppNameArray[i].threadId == threadId) + return (ulogAppNameArray[i].appName); + } + + // setting for this thread not found, return app-wide setting. + return ulogAppName; +} + + +void bcmuLog_setEidToThreadId(UINT32 eid, SINT32 threadId) +{ + UINT32 i; + + // First check for modification to existing entry. + for (i=0; i < BCMULOG_NUM_THREAD_SLOTS; i++) + { + if (ulogEidToThreadIdArray[i].eid == eid) + { + ulogEidToThreadIdArray[i].threadId = threadId; + return; + } + } + + // New mapping entry, try to find an empty slot. + for (i=0; i < BCMULOG_NUM_THREAD_SLOTS; i++) + { + if (ulogEidToThreadIdArray[i].eid == 0) + { + ulogEidToThreadIdArray[i].eid = eid; + ulogEidToThreadIdArray[i].threadId = threadId; + ulogEidToThreadIdEntries++; + return; + } + } + + // No more empty slots. + // TODO: there is no mechanism to clear a slot after it has been set. + // Assuming all of these threads are long-lived. + bcmuLog_error("BCM uLog (eidToThreadId) table full (max=%d)", + BCMULOG_NUM_THREAD_SLOTS); + return; +} + +SINT32 bcmuLog_getEidToThreadId(UINT32 eid) +{ + UINT32 i; + + // Don't bother scanning through the array if there are no entries. + if (ulogEidToThreadIdEntries == 0) + return 0; + + for (i=0; i < BCMULOG_NUM_THREAD_SLOTS; i++) + { + if (ulogEidToThreadIdArray[i].eid == eid) + { + return ulogEidToThreadIdArray[i].threadId; + } + } + + return 0; +} + +static void fillFormatInfo(BcmuLogLevel level, + const char *funcName, + UINT32 lineNum, + BcmuLogFormatInfo *info) +{ + SINT32 threadId = sysUtl_getThreadId(); + + memset(info, 0, sizeof(BcmuLogFormatInfo)); + info->logLevel = level; + info->logDestMask = bcmuLog_getDestMaskEx(threadId, 0); + info->logHeaderMask = bcmuLog_getHdrMaskEx(threadId, 0); + info->lineNum = lineNum; + strncpy(info->funcName, funcName, sizeof(info->funcName)-1); + if (ulogAppName[0] == '\0') + { + bcmuLog_setNameFromProc(); + } + strncpy(info->appName, bcmuLog_getNameEx(threadId, 0), sizeof(info->appName)-1); +} + +static void outputLogBuf(int level, const char *buf) +{ + if (ulogDestMask & BCMULOG_DESTMASK_STDERR) + { + fprintf(stderr, "%s\n", buf); + fflush(stderr); + } + + if (ulogDestMask & BCMULOG_DESTMASK_SYSLOG) + { + /* use of openlog is optional, so just call syslog */ + syslog(level, "%s", buf); + } + + // Now that CMS Log uses ulogDestMask to store its own log destination + // state, it is possible uLogDestkMask has the telnet bit set. Ignore it + // for now. + return; +} + +void ulog_log(BcmuLogLevel level, const char *funcName, UINT32 lineNum, const char *pFmt, ... ) +{ + char *logBuf = NULL; + size_t bufSize; + BcmuLogFormatInfo info; + FILE *stream = NULL; + SINT32 threadId; + va_list ap; + + threadId = sysUtl_getThreadId(); + if (level > bcmuLog_getLevelEx(threadId, 0)) + { + return; + } + + stream = open_memstream(&logBuf, &bufSize); + if (stream == NULL) + { + printf("Failed to open memory stream!\n"); + return; + } + + fillFormatInfo(level, funcName, lineNum, &info); + va_start(ap, pFmt); + bcmuLog_formatLine(stream, &info, pFmt, ap); + va_end(ap); + + fflush(stream); + fclose(stream); + + outputLogBuf(level, logBuf); + free(logBuf); +} + +static void outputTraceBuf(const char *buf) +{ + + if (uTraceDestMask & BCMULOG_DESTMASK_STDERR) + { + fprintf(stderr, "%s\n", buf); + fflush(stderr); + } + + if (uTraceDestMask & BCMULOG_DESTMASK_SYSLOG) + { + syslog(LOG_DEBUG, "%s", buf); + } + + return; +} + +void ulog_trace(const char *funcName, UINT32 lineNum, const char *anchor, const char *pFmt, ... ) +{ + char *logBuf = NULL; + size_t bufSize; + BcmuLogFormatInfo info; + FILE *stream = NULL; + va_list ap; + + stream = open_memstream(&logBuf, &bufSize); + if (stream == NULL) + { + printf("Failed to open memory stream!\n"); + return; + } + + fillFormatInfo(BCMULOG_LEVEL_PERFTRACE, funcName, lineNum, &info); + va_start(ap, pFmt); + bcmuLog_formatPerfTrace(stream, &info, anchor, pFmt, ap); + va_end(ap); + + fflush(stream); + fclose(stream); + + outputTraceBuf(logBuf); + free(logBuf); +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ulog.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ulog.h new file mode 100644 index 00000000000..9bd8a75df9d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcm_util/bcm_ulog.h @@ -0,0 +1,260 @@ +/*********************************************************************** + * + * Copyright (c) 2018 Broadcom Ltd + * All Rights Reserved + * + * <:label-BRCM:2018:DUAL/GPL:standard + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * +:> + * +************************************************************************/ + +#ifndef __BCM_ULOG_H__ +#define __BCM_ULOG_H__ + +#if defined __cplusplus +extern "C" { +#endif + + +#include +#include +#include "number_defs.h" + +/*!\file bcm_ulog.h + * \brief Broadcom Userspace Logging utility. + * + * Broadcom apps and daemons which do not want to have dependencies on CMS + * can use this logging system instead of CMS logging. They are very similar, + * and CMS logging even uses this logging system for formatting the log line. + * + * Basically, your code can just call the various bcmuLog_error, + * bcmuLog_notice, and bcmuLog_debug macros. There is no need to call an + * "init" function. Optionally, you can modify the logging level, destination, + * or the meta info in the log line by calling the various bcmuLog_set + * functions. + */ + + /*!\enum BcmuLogLevel + * \brief Logging levels. + * These must be the same as LINUX syslog levels. + */ + typedef enum + { + BCMULOG_LEVEL_ERR = 3, /**< Message at error level. */ + BCMULOG_LEVEL_NOTICE = 5, /**< Message at notice level. */ + BCMULOG_LEVEL_DEBUG = 7, /**< Message at debug level. */ + BCMULOG_LEVEL_PERFTRACE = 256 /**< Message at trace level. */ + } BcmuLogLevel; + + #define BCMULOG_DEFAULT_LEVEL BCMULOG_LEVEL_ERR + + #define bcmuLog_error(args...) ulog_log(BCMULOG_LEVEL_ERR, __FUNCTION__, __LINE__, args) + #define bcmuLog_notice(args...) ulog_log(BCMULOG_LEVEL_NOTICE, __FUNCTION__, __LINE__, args) + #define bcmuLog_debug(args...) ulog_log(BCMULOG_LEVEL_DEBUG, __FUNCTION__, __LINE__, args) + #define bcmuLog_perftrace_begin(args...) ulog_trace(__FUNCTION__, __LINE__, ">>>", args) + #define bcmuLog_perftrace_end(args...) ulog_trace(__FUNCTION__, __LINE__, "<<<", args) + + +/** Set the app-wide logging level */ +void bcmuLog_setLevel(UINT32 level); + +/** Set the log level for a specific thread or eid. + * threadId and/or eid must be specified. + * If only threadId is specified, that is ok. + * If only eid is specified, then a EID to threadId mapping must already exist. + * If both threadId and eid are specified, then this call will also create + * a EID to threadId mapping. + * Internally, the thread specific log level is associated with the threadId. + */ +void bcmuLog_setLevelEx(UINT32 level, SINT32 threadId, UINT32 eid); + +/** Get the app-wide logging level */ +UINT32 bcmuLog_getLevel(void); + +/** Get the log level for a specific thread or eid. + * The use of threadId and eid is the same as bcmuLog_setLevelEx(). + * If no thread or eid specific setting is found, the app wide-setting is + * returned. + */ +UINT32 bcmuLog_getLevelEx(SINT32 threadId, UINT32 eid); + + +/** Set the meta info on the log line, see HDRMASK_xxx */ +void bcmuLog_setHdrMask(UINT32 mask); + +/** Set the header mask for a specific thread or eid. + * See comments above for setLevelEx. + */ +void bcmuLog_setHdrMaskEx(UINT32 mask, SINT32 threadId, UINT32 eid); + +/** Return the header mask, see HDRMASK_xxx */ +UINT32 bcmuLog_getHdrMask(void); + +/** Get the header mask for a specific thread or eid. + * See comments above for getLevelEx. + */ +UINT32 bcmuLog_getHdrMaskEx(SINT32 threadId, UINT32 eid); + + +/** Set where the log lines go. */ +void bcmuLog_setDestMask(UINT32 mask); + +/** Set the destination mask for a specific thread or eid. + * See comments above for setLevelEx. + */ +void bcmuLog_setDestMaskEx(UINT32 mask, SINT32 threadId, UINT32 eid); + +/** Get the destination mask */ +UINT32 bcmuLog_getDestMask(); + +/** Get the destination mask for a specific thread or eid. + * See comments above for getLevelEx. + */ +UINT32 bcmuLog_getDestMaskEx(SINT32 threadId, UINT32 eid); + + +/** set the app name on the log line. Used with HDRMASK_APPNAME. + * + * This call is optional. If the app name has not been explicitly set, + * bcmuLog will automatially get the app's name by calling + * bcmuLog_getNameFromProc(). However, Linux limits the app name in + * /proc/self/comm to 15 characters. Whereas bcmuLog_setName() allows up to + * BCMULOG_MAX_APP_NAME_LEN characters for the name. + */ +void bcmuLog_setName(const char *name); + +/** set the app name from /proc entry. */ +void bcmuLog_setNameFromProc(); + +/** Set the thread name for a specific thread or eid. + * See comments above for setLevelEx. + */ +void bcmuLog_setNameEx(const char *name, SINT32 threadId, UINT32 eid); + +/** Get the app name */ +const char *bcmuLog_getName(void); + +/** Get the thread name for a specific thread or eid. + * See comments above for getLevelEx. + */ +const char *bcmuLog_getNameEx(SINT32 threadId, UINT32 eid); + + +/** Map EID to threadId. Assumes one-to-one EID to threadId mapping. Does not + * work if there are multiple threads or processes associated with a single + * EID, e.g. ppp. + */ +void bcmuLog_setEidToThreadId(UINT32 eid, SINT32 threadId); + +SINT32 bcmuLog_getEidToThreadId(UINT32 eid); + + +/** Show application name in the log line. */ +#define BCMULOG_HDRMASK_APPNAME 0x0001 + +/** Show log level in the log line. */ +#define BCMULOG_HDRMASK_LEVEL 0x0002 + +/** Show timestamp in the log line. */ +#define BCMULOG_HDRMASK_TIMESTAMP 0x0004 + +/** Show location (function name and line number) level in the log line. */ +#define BCMULOG_HDRMASK_LOCATION 0x0008 + +/** Show thread id of calling thread. For single threaded apps, thread id is + * the same as process id. */ +#define BCMULOG_HDRMASK_THREAD_ID 0x0010 + +/** Default header mask */ +#define BCMULOG_DEFAULT_HDRMASK (BCMULOG_HDRMASK_APPNAME|BCMULOG_HDRMASK_LEVEL|BCMULOG_HDRMASK_TIMESTAMP|BCMULOG_HDRMASK_LOCATION) + + +/** Send log to stderr */ +#define BCMULOG_DESTMASK_STDERR 0x0001 + +/** Send log to syslog */ +#define BCMULOG_DESTMASK_SYSLOG 0x0002 + +/** CMS logging had concept of logging to telnet window. support that? */ +#define BCMULOG_DESTMASK_TELNET 0x0004 + +/** Send log to file (not supported yet. maybe merge with action log?) */ +#define BCMULOG_DESTMASK_FILE 0x0010 + +/** default destination mask */ +#define BCMULOG_DEFAULT_DESTMASK (BCMULOG_DESTMASK_STDERR) + + +/** Max length of the app name in the log line. */ +#define BCMULOG_MAX_APP_NAME_LEN 64 + +/** Max length of the function name where the logging line is. */ +#define BCMULOG_MAX_FUNC_NAME_LEN 128 + +/** Max length of log line. */ +#define BCMULOG_MAX_LINE_LEN 512 + +/** All the info needed by the log line formatter. */ +typedef struct bcm_ulog_format_info +{ + UINT32 logLevel; + UINT32 logDestMask; + UINT32 logHeaderMask; + UINT32 lineNum; + char funcName[BCMULOG_MAX_FUNC_NAME_LEN]; + char appName[BCMULOG_MAX_APP_NAME_LEN]; +} BcmuLogFormatInfo; + + +/** Create a log line based on setting in BcmuLogFormatInfo. + * + * This function is shared by bcm_ulog and CMS log. +*/ +void bcmuLog_formatLine(FILE *stream, BcmuLogFormatInfo *info, const char *pFmt, va_list ap); + +void bcmuLog_formatPerfTrace(FILE *stream, BcmuLogFormatInfo *info, const char *anchor, const char *pFmt, va_list ap); + +/** Do not call this function directly. Use the bcmuLog_{error, notice, debug} + * macros instead. + */ +void ulog_log(BcmuLogLevel level, const char *funcName, UINT32 lineNum, const char *pFmt, ... ); + +void ulog_trace(const char *funcName, UINT32 lineNum, const char *anchor, const char *pFmt, ... ); + + +#define BCMULOG_NUM_THREAD_SLOTS 4 + +typedef struct bcm_ulog_thread_info +{ + SINT32 threadId; // only threadId as lookup key is supported. + UINT32 eid; // used for mapping EID to threadid. + UINT32 value; // logLevel, logDestMask, or logHdrMask; + char appName[BCMULOG_MAX_APP_NAME_LEN]; // more accurately: thread name +} BcmuLogThreadInfo; + + +#if defined __cplusplus +}; +#endif +#endif /* __BCM_ULOG_H__ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/cfg-bcmdrv.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/cfg-bcmdrv.mk new file mode 100644 index 00000000000..e9a9c3b6582 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/cfg-bcmdrv.mk @@ -0,0 +1,24 @@ +# Makefile fragment for bcmdrv-specific configuration. +# +# Copyright (C) 2022, Broadcom. All Rights Reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# +# <> +# +# $Id$ +# + +bcmdrv_IncDirs := include include/ctf include/emf/emf include/emf/igs +bcmdrv_SrcDirs := shared diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/armca9_core.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/armca9_core.h new file mode 100644 index 00000000000..43541fcc271 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/armca9_core.h @@ -0,0 +1,65 @@ +/* + * ARM CA9 (iHost) definitions + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: armca9_core.h 596126 2015-10-29 19:53:48Z $ + */ + +#ifndef _armca9_core_h_ +#define _armca9_core_h_ + +#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) + +/* cpp contortions to concatenate w/arg prescan */ +#ifndef PAD +#define _PADLINE(line) pad ## line +#define _XSTR(line) _PADLINE(line) +#define PAD _XSTR(__LINE__) +#endif /* PAD */ + +typedef volatile struct { + uint32 PAD[1024]; +} armca9regs_t; + +#endif /* !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) */ + +#define IHOST_PROC_CLK_WR_ACCESS 0x19000000 +#define IHOST_PROC_CLK_POLICY_FREQ 0x19000008 +#define IHOST_PROC_CLK_POLICY_CTL 0x1900000c +#define IHOST_PROC_CLK_POLICY_CTL__GO 0 +#define IHOST_PROC_CLK_POLICY_CTL__GO_AC 1 + +#define IHOST_PROC_CLK_CORE0_CLKGATE 0x19000200 +#define IHOST_PROC_CLK_CORE1_CLKGATE 0x19000204 +#define IHOST_PROC_CLK_ARM_SWITCH_CLKGATE 0x19000210 +#define IHOST_PROC_CLK_ARM_PERIPH_CLKGATE 0x19000300 +#define IHOST_PROC_CLK_APB0_CLKGATE 0x19000400 + +#define IHOST_PROC_CLK_PLLARMA 0x19000c00 +#define IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB 1 +#define IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK 28 + +/* SCU registers */ +#define IHOST_SCU_CONTROL 0x19020000 +#define IHOST_SCU_INVALIDATE 0x1902000c + +/* L2C registers */ +#define IHOST_L2C_CACHE_ID 0x19022000 + +#endif /* _armca9_core_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/bcmrobo.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/bcmrobo.h new file mode 100644 index 00000000000..201c422df38 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/bcmrobo.h @@ -0,0 +1,184 @@ +/* + * RoboSwitch setup functions + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: bcmrobo.h 670098 2016-11-14 09:42:29Z $ + */ + +#ifndef _bcm_robo_h_ +#define _bcm_robo_h_ + +#define DEVID5325 0x25 /* 5325 (Not really but we fake it) */ +#define DEVID5395 0x95 /* 5395 */ +#define DEVID5397 0x97 /* 5397 */ +#define DEVID5398 0x98 /* 5398 */ +#define DEVID53115 0x3115 /* 53115 */ +#define DEVID53125 0x3125 /* 53125 */ + +/* + * MODELID: + * 0x53010: BCM4707, Select Low SKU device if SKU ID[1:0] = 01. + * 0x53011: BCM4708, Select Middle SKU device if SKU ID[1:0] = 10. + * 0x53012: BCM4709, Select High SKU device if SKU ID[1:0] = 00. + * Note: The SKU ID[1:0] is loaded from OTP configuration data. + */ +#define DEVID53010 0x53010 /* 53010 */ +#define DEVID53011 0x53011 /* 53011 */ +#define DEVID53012 0x53012 /* 53012 */ +#define DEVID53018 0x53018 /* 53018 */ +#define DEVID53019 0x53019 /* 53019 */ +#define DEVID53030 0x53030 /* 53030 */ +#define ROBO_IS_BCM5301X(id) ((id) == DEVID53010 || (id) == DEVID53011 || (id) == DEVID53012 || \ +(id) == DEVID53018 || (id) == DEVID53019 || (id) == DEVID53030) + +/* Power save duty cycle times */ +#define MAX_NO_PHYS 5 +#define PWRSAVE_SLEEP_TIME 12 +#define PWRSAVE_WAKE_TIME 3 + +/* Power save modes for the switch */ +#define ROBO_PWRSAVE_NORMAL 0 +#define ROBO_PWRSAVE_AUTO 1 +#define ROBO_PWRSAVE_MANUAL 2 +#define ROBO_PWRSAVE_AUTO_MANUAL 3 + +#define ROBO_IS_PWRSAVE_MANUAL(r) ((r)->pwrsave_mode_manual) +#define ROBO_IS_PWRSAVE_AUTO(r) ((r)->pwrsave_mode_auto) + +/* SRAB interface */ +/* Access switch registers through SRAB (Switch Register Access Bridge) */ +#define REG_VERSION_ID 0x40 +#define REG_CTRL_PORT0_GMIIPO 0x58 /* 53012: GMII Port0 Override register */ +#define REG_CTRL_PORT1_GMIIPO 0x59 /* 53012: GMII Port1 Override register */ +#define REG_CTRL_PORT2_GMIIPO 0x5a /* 53012: GMII Port2 Override register */ +#define REG_CTRL_PORT3_GMIIPO 0x5b /* 53012: GMII Port3 Override register */ +#define REG_CTRL_PORT4_GMIIPO 0x5c /* 53012: GMII Port4 Override register */ +#define REG_CTRL_PORT5_GMIIPO 0x5d /* 53012: GMII Port5 Override register */ +#define REG_CTRL_PORT7_GMIIPO 0x5f /* 53012: GMII Port7 Override register */ + +/* Command and status register of the SRAB */ +#define CFG_F_sra_rst_MASK (1 << 2) +#define CFG_F_sra_write_MASK (1 << 1) +#define CFG_F_sra_gordyn_MASK (1 << 0) +#define CFG_F_sra_page_R 24 +#define CFG_F_sra_offset_R 16 + +/* Switch interface controls */ +#define CFG_F_sw_init_done_MASK (1 << 6) +#define CFG_F_rcareq_MASK (1 << 3) +#define CFG_F_rcagnt_MASK (1 << 4) + +#ifndef PAD +#define _PADLINE(line) pad ## line +#define _XSTR(line) _PADLINE(line) +#define PAD _XSTR(__LINE__) +#endif /* PAD */ + +typedef volatile struct { + uint32 PAD[11]; + uint32 cmdstat; /* 0x2c, command and status register of the SRAB */ + uint32 wd_h; /* 0x30, high order word of write data to switch registe */ + uint32 wd_l; /* 0x34, low order word of write data to switch registe */ + uint32 rd_h; /* 0x38, high order word of read data from switch register */ + uint32 rd_l; /* 0x3c, low order word of read data from switch register */ + uint32 ctrls; /* 0x40, switch interface controls */ + uint32 intr; /* 0x44, the register captures interrupt pulses from the switch */ +} srabregs_t; + +/* Forward declaration */ +typedef struct robo_info_s robo_info_t; + +/* Device access/config oprands */ +typedef struct { + /* low level routines */ + void (*enable_mgmtif)(robo_info_t *robo); /* enable mgmt i/f, optional */ + void (*disable_mgmtif)(robo_info_t *robo); /* disable mgmt i/f, optional */ + int (*write_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); + int (*read_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); + /* description */ + char *desc; +} dev_ops_t; + +typedef uint16 (*miird_f)(void *h, int add, int off); +typedef void (*miiwr_f)(void *h, int add, int off, uint16 val); + +/* Private state per RoboSwitch */ +struct robo_info_s { + si_t *sih; /* SiliconBackplane handle */ + char *vars; /* nvram variables handle */ + void *h; /* dev handle */ + uint32 devid; /* Device id for the switch */ + uint32 corerev; /* Core rev of internal switch */ + + dev_ops_t *ops; /* device ops */ + uint8 page; /* current page */ + + /* SPI */ + uint32 ss, sck, mosi, miso; /* GPIO mapping */ + + /* MII */ + miird_f miird; + miiwr_f miiwr; + + /* SRAB */ + srabregs_t *srabregs; + + uint16 prev_status; /* link status of switch ports */ + uint32 pwrsave_mode_manual; /* bitmap of ports in manual power save */ + uint32 pwrsave_mode_auto; /* bitmap of ports in auto power save mode */ + uint32 pwrsave_sleep_time; /* sleep time for manual power save mode */ + uint32 pwrsave_wake_time; /* wakeup time for manual power save mode */ + uint8 pwrsave_phys; /* Phys that can be put into power save mode */ + uint8 pwrsave_mode_phys[MAX_NO_PHYS]; /* Power save mode on the switch */ + bool eee_status; +#ifdef BCMFA + int aux_pid; +#endif /* BCMFA */ +}; + +/* Power Save mode related functions */ +extern int32 robo_power_save_mode_get(robo_info_t *robo, int32 phy); +extern int32 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy); +extern void robo_power_save_mode_update(robo_info_t *robo); +extern int robo_power_save_mode(robo_info_t *robo, int mode, int phy); +extern int robo_power_save_toggle(robo_info_t *robo, int normal); + +extern robo_info_t *bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr); +extern void bcm_robo_detach(robo_info_t *robo); +extern int bcm_robo_enable_device(robo_info_t *robo); +extern int bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr); +extern int bcm_robo_enable_switch(robo_info_t *robo); +extern int bcm_robo_flow_control(robo_info_t *robo, bool set); + +#ifdef BCMDBG +extern void robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b); +#endif /* BCMDBG */ + +extern void robo_watchdog(robo_info_t *robo); +extern void robo_eee_advertise_init(robo_info_t *robo); + +#ifdef BCMFA +extern void robo_fa_aux_init(robo_info_t *robo); +extern void robo_fa_aux_enable(robo_info_t *robo, bool enable); +extern void robo_fa_enable(robo_info_t *robo, bool on, bool bhdr); +#endif + +extern void bcm_robo_check_gphy_reset(robo_info_t *robo, uint8 page, uint8 reg, + void *val, int len); +#endif /* _bcm_robo_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/ctf/ctf_cfg.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/ctf/ctf_cfg.h new file mode 100644 index 00000000000..97f0a3bde59 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/ctf/ctf_cfg.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: $ + */ + +#ifndef _CTF_CFG_H_ +#define _CTF_CFG_H_ + +#define NETLINK_CTF 20 + +#define SUCCESS 0 +#define FAILURE -1 + +#define CTFCFG_MAX_SIZE sizeof(ctf_cfg_request_t) +#define CTFCFG_MAX_ARG_SIZE 1024 + +#define CTFCFG_CMD_SUSPEND 1 +#define CTFCFG_CMD_RESUME 2 +#define CTFCFG_CMD_TUPLE_VALID 3 +#define CTFCFG_CMD_DEFAULT_FWD_GET 4 +#define CTFCFG_CMD_DEFAULT_FWD_SET 5 +#define CTFCFG_CMD_UPD_MARK 6 +#define CTFCFG_CMD_CHANGE_TXIF_TO_BR 7 + +#define CTFCFG_STATUS_SUCCESS 1 +#define CTFCFG_STATUS_FAILURE 2 +#define CTFCFG_STATUS_TUPLE_INVALID 3 +#define CTFCFG_STATUS_FLOW_ALREADY_SUSPENDED 4 +#define CTFCFG_STATUS_FLOW_NOT_SUSPENDED 5 +#define CTFCFG_STATUS_DEFAULT_FWD_INVALID 6 +#define CTFCFG_STATUS_PROTOCOL_NOT_SUPPORTED 7 + +typedef union +{ + struct in_addr ip_v4; + struct in6_addr ip_v6; +} ip_address_t; + +typedef struct +{ + int family; + + ip_address_t src_addr; + ip_address_t dst_addr; + + uint16_t src_port; + uint16_t dst_port; + + uint8_t protocol; +} ctf_tuple_t; + +typedef enum { + CTF_FWD_FASTPATH, + CTF_FWD_HOST, /* i.e. send to network stack */ +} ctf_fwd_t; + +typedef struct ctf_cfg_request +{ + uint32_t command_id; + uint32_t status; /* Command status */ + uint32_t size; /* Size of the argument */ + uint8_t arg[CTFCFG_MAX_ARG_SIZE]; +} ctf_cfg_request_t; + +#endif /* _CTF_CFG_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/ctf/hndctf.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/ctf/hndctf.h new file mode 100644 index 00000000000..8a92cf284a3 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/ctf/hndctf.h @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: hndctf.h 676803 2016-12-24 20:04:01Z $ + */ + +#ifndef _HNDCTF_H_ +#define _HNDCTF_H_ + +#include +#include +#include +#include + +/* + * Define to enable couting VLAN tx and rx packets and bytes. This could be + * disabled if the functionality has impact on performance. + */ +#define CTFVLSTATS + +#define CTF_ENAB(ci) (((ci) != NULL) && (ci)->_ctf) + +#define CTF_ACTION_TAG (1 << 0) +#define CTF_ACTION_UNTAG (1 << 1) +#define CTF_ACTION_SNAT (1 << 2) +#define CTF_ACTION_DNAT (1 << 3) +#define CTF_ACTION_SUSPEND (1 << 4) +#define CTF_ACTION_TOS (1 << 5) +#define CTF_ACTION_MARK (1 << 6) +#define CTF_ACTION_BYTECNT (1 << 7) +#define CTF_ACTION_PPPOE_ADD (1 << 8) +#define CTF_ACTION_PPPOE_DEL (1 << 9) +#define CTF_ACTION_BR_AS_TXIF (1 << 10) +#define CTF_ACTION_PPTP_ADD (1 << 11) +#define CTF_ACTION_PPTP_DEL (1 << 12) +#define CTF_ACTION_L2TP_ADD (1 << 13) +#define CTF_ACTION_L2TP_DEL (1 << 14) + +#define CTF_SUSPEND_TCP (1 << 0) +#define CTF_SUSPEND_UDP (1 << 1) + +#define CTF_SUSPEND_TCP_MASK 0x55555555 +#define CTF_SUSPEND_UDP_MASK 0xAAAAAAAA + +#define ctf_attach(osh, n, m, c, a) \ + (ctf_attach_fn ? ctf_attach_fn(osh, n, m, c, a) : NULL) +#define ctf_forward(ci, p, d) (ci)->fn.forward(ci, p, d) +#define ctf_isenabled(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isenabled(ci, d) : FALSE) +#define ctf_isbridge(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isbridge(ci, d) : FALSE) +#define ctf_enable(ci, d, e, b) (CTF_ENAB(ci) ? (ci)->fn.enable(ci, d, e, b) : BCME_OK) +#define ctf_brc_add(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_add(ci, b) : BCME_OK) +#define ctf_brc_delete(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_delete(ci, e) : BCME_OK) +#define ctf_brc_lkup(ci, e, l) (CTF_ENAB(ci) ? (ci)->fn.brc_lkup(ci, e, l) : NULL) +#define ctf_brc_acquire(ci) do { if (CTF_ENAB(ci)) (ci)->fn.brc_acquire(ci); } while (0) +#define ctf_brc_release(ci) do { if (CTF_ENAB(ci)) (ci)->fn.brc_release(ci); } while (0) +#define ctf_ipc_add(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.ipc_add(ci, i, v6) : BCME_OK) +#define ctf_ipc_delete(ci, i, v6) \ + (CTF_ENAB(ci) ? (ci)->fn.ipc_delete(ci, i, v6) : BCME_OK) +#define ctf_ipc_count_get(ci, i) \ + (CTF_ENAB(ci) ? (ci)->fn.ipc_count_get(ci, i) : BCME_OK) +#define ctf_ipc_delete_multi(ci, i, im, v6) \ + (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_multi(ci, i, im, v6) : BCME_OK) +#define ctf_ipc_delete_range(ci, s, e, v6) \ + (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_range(ci, s, e, v6) : BCME_OK) +#define ctf_ipc_action(ci, s, e, am, v6) \ + (CTF_ENAB(ci) ? (ci)->fn.ipc_action(ci, s, e, am, v6) : BCME_OK) +#define ctf_ipc_lkup(ci, i, v6) \ + (CTF_ENAB(ci) ? (ci)->fn.ipc_lkup(ci, i, v6) : NULL) +#ifdef CTF_IPV6 +#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (CTF_ENAB(ci) && (ci)->fn.ipc_lkup_l4proto? \ + (ci)->fn.ipc_lkup_l4proto((uint8 *)iph, l4p) : NULL) +#else +#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (NULL) +#endif /* CTF_IPV6 */ +#define ctf_ipc_release(ci, i) do { if (CTF_ENAB(ci)) (ci)->fn.ipc_release(ci, i); } while (0) +#define ctf_dev_register(ci, d, b) \ + (CTF_ENAB(ci) ? (ci)->fn.dev_register(ci, d, b) : BCME_OK) +#define ctf_dev_vlan_add(ci, d, vid, vd) \ + (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_add(ci, d, vid, vd) : BCME_OK) +#define ctf_dev_vlan_delete(ci, d, vid) \ + (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_delete(ci, d, vid) : BCME_OK) +#define ctf_detach(ci) if (CTF_ENAB(ci)) (ci)->fn.detach(ci) +#define ctf_dump(ci, b) if (CTF_ENAB(ci)) (ci)->fn.dump(ci, b) +#define ctf_cfg_req_process(ci, c) if (CTF_ENAB(ci)) (ci)->fn.cfg_req_process(ci, c) +#define ctf_dev_unregister(ci, d) if (CTF_ENAB(ci)) (ci)->fn.dev_unregister(ci, d) +#ifdef BCMFA +#define ctf_fa_register(ci, d, i) if (CTF_ENAB(ci)) (ci)->fn.fa_register(ci, d, i) +#define ctf_live(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.live(ci, i, v6) : FALSE) +#endif /* BCMFA */ + +/* For broadstream iqos */ +#define ctf_fwdcb_register(ci, cb) \ + (CTF_ENAB(ci) ? (ci)->fn.ctf_fwdcb_register(ci, cb) : BCME_OK) + +#define CTFCNTINCR(s) ((s)++) +#define CTFCNTADD(s, c) ((s) += (c)) + +/* Copy an ethernet address in reverse order */ +#define ether_rcopy(s, d) \ +do { \ + ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \ + ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \ + ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \ +} while (0) + +#define NIPQUAD(addr) \ + ((unsigned char *)&addr)[0], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[3] + +#ifdef CTF_PPTP +#define ctf_pptp_cache(ci, f, h) (CTF_ENAB((ci)) ? ((ci))->fn.pptp_cache((ci), (f), (h)) : BCME_OK) +#endif /* CTF_PPTP */ + +#define PPPOE_ETYPE_OFFSET 12 +#define PPPOE_VER_OFFSET 14 +#define PPPOE_SESID_OFFSET 16 +#define PPPOE_LEN_OFFSET 18 + +#define PPPOE_HLEN 20 +#define PPPOE_PPP_HLEN 8 + +#define PPPOE_PROT_PPP 0x0021 +#define PPPOE_PROT_PPP_IP6 0x0057 + +#define CTF_DROP_PACKET -2 /* Don't osl_startxmit if fwdcb return this */ + +typedef struct ctf_pub ctf_t; +typedef struct ctf_brc ctf_brc_t; +typedef struct ctf_ipc ctf_ipc_t; +typedef struct ctf_conn_tuple ctf_conn_tuple_t; +typedef struct ctf_brc_hot ctf_brc_hot_t; + +typedef void (*ctf_detach_cb_t)(ctf_t *ci, void *arg); +typedef ctf_t * (*ctf_attach_t)(osl_t *osh, uint8 *name, uint32 *msg_level, + ctf_detach_cb_t cb, void *arg); +typedef void (*ctf_detach_t)(ctf_t *ci); +typedef int32 (*ctf_forward_t)(ctf_t *ci, void *p, void *rxifp); +typedef bool (*ctf_isenabled_t)(ctf_t *ci, void *dev); +typedef bool (*ctf_isbridge_t)(ctf_t *ci, void *dev); +typedef void (*ctf_brc_acquire_t)(ctf_t *ci); +typedef void (*ctf_brc_release_t)(ctf_t *ci); +typedef int32 (*ctf_brc_add_t)(ctf_t *ci, ctf_brc_t *brc); +typedef int32 (*ctf_brc_delete_t)(ctf_t *ci, uint8 *ea); +typedef ctf_brc_t * (*ctf_brc_lkup_t)(ctf_t *ci, uint8 *da, bool lock_taken); +typedef int32 (*ctf_ipc_add_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); +typedef int32 (*ctf_ipc_delete_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); +typedef int32 (*ctf_ipc_count_get_t)(ctf_t *ci); +typedef int32 (*ctf_ipc_delete_multi_t)(ctf_t *ci, ctf_ipc_t *ipc, + ctf_ipc_t *ipcm, bool v6); +typedef int32 (*ctf_ipc_delete_range_t)(ctf_t *ci, ctf_ipc_t *start, + ctf_ipc_t *end, bool v6); +typedef int32 (*ctf_ipc_action_t)(ctf_t *ci, ctf_ipc_t *start, + ctf_ipc_t *end, uint32 action_mask, bool v6); +typedef ctf_ipc_t * (*ctf_ipc_lkup_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); +typedef uint8 * (*ctf_ipc_lkup_l4proto_t)(uint8 *iph, uint8 *proto_num); +typedef void (*ctf_ipc_release_t)(ctf_t *ci, ctf_ipc_t *ipc); +typedef int32 (*ctf_enable_t)(ctf_t *ci, void *dev, bool enable, ctf_brc_hot_t **brc_hot); +typedef int32 (*ctf_dev_register_t)(ctf_t *ci, void *dev, bool br); +typedef void (*ctf_dev_unregister_t)(ctf_t *ci, void *dev); +typedef int32 (*ctf_dev_vlan_add_t)(ctf_t *ci, void *dev, uint16 vid, void *vldev); +typedef int32 (*ctf_dev_vlan_delete_t)(ctf_t *ci, void *dev, uint16 vid); +typedef void (*ctf_dump_t)(ctf_t *ci, struct bcmstrbuf *b); +typedef void (*ctf_cfg_req_process_t)(ctf_t *ci, void *arg); +#ifdef BCMFA +typedef int (*ctf_fa_cb_t)(void *dev, ctf_ipc_t *ipc, bool v6, int cmd); + +typedef int32 (*ctf_fa_register_t)(ctf_t *ci, ctf_fa_cb_t facb, void *fa); +typedef void (*ctf_live_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); +#endif /* BCMFA */ + +#ifdef CTF_PPTP +typedef int32 (*ctf_pptp_cache_t)(ctf_t *ci, uint32 lock_fgoff, uint32 hoplmt); +#endif /* CTF_PPTP */ + +/* For broadstream iqos */ +typedef int (*ctf_fwdcb_t)(void *skb, ctf_ipc_t *ipc); +typedef int32 (*ctf_fwdcb_register_t)(ctf_t *ci, ctf_fwdcb_t fwdcb); + +struct ctf_brc_hot { + struct ether_addr ea; /* Dest address */ + ctf_brc_t *brcp; /* BRC entry corresp to dest mac */ +}; + +typedef struct ctf_fn { + ctf_detach_t detach; + ctf_forward_t forward; + ctf_isenabled_t isenabled; + ctf_isbridge_t isbridge; + ctf_brc_add_t brc_add; + ctf_brc_delete_t brc_delete; + ctf_brc_lkup_t brc_lkup; + ctf_brc_acquire_t brc_acquire; + ctf_brc_release_t brc_release; + ctf_ipc_add_t ipc_add; + ctf_ipc_delete_t ipc_delete; + ctf_ipc_count_get_t ipc_count_get; + ctf_ipc_delete_multi_t ipc_delete_multi; + ctf_ipc_delete_range_t ipc_delete_range; + ctf_ipc_action_t ipc_action; + ctf_ipc_lkup_t ipc_lkup; + ctf_ipc_lkup_l4proto_t ipc_lkup_l4proto; + ctf_ipc_release_t ipc_release; + ctf_enable_t enable; + ctf_dev_register_t dev_register; + ctf_dev_unregister_t dev_unregister; + ctf_detach_cb_t detach_cb; + void *detach_cb_arg; + ctf_dev_vlan_add_t dev_vlan_add; + ctf_dev_vlan_delete_t dev_vlan_delete; +#ifdef CTF_PPTP + ctf_pptp_cache_t pptp_cache; +#endif /* CTF_PPTP */ + ctf_dump_t dump; + ctf_cfg_req_process_t cfg_req_process; +#ifdef BCMFA + ctf_fa_register_t fa_register; + ctf_live_t live; +#endif /* BCMFA */ + /* For broadstream iqos */ + ctf_fwdcb_register_t ctf_fwdcb_register; +} ctf_fn_t; + +struct ctf_pub { + bool _ctf; /* Global CTF enable/disable */ + ctf_fn_t fn; /* Exported functions */ + void *nl_sk; /* Netlink socket */ + uint32 ipc_suspend; /* Global IPC suspend flags */ +}; + +/* Connection Mark */ +typedef struct ctf_mark { + uint32 value; +} ctf_mark_t; + +struct ctf_brc { + struct ctf_brc *next; /* Pointer to brc entry */ + struct ether_addr dhost; /* MAC addr of host */ + uint16 vid; /* VLAN id to use on txif */ + void *txifp; /* Interface connected to host */ + uint32 action; /* Tag or untag the frames */ + uint32 live; /* Counter used to expire the entry */ + uint32 hits; /* Num frames matching brc entry */ + uint64 *bytecnt_ptr; /* Pointer to the byte counter */ + uint32 hitting; /* Indicate how fresh the entry is been used */ + uint32 ip; +}; + +#ifdef CTF_IPV6 +#define IPADDR_U32_SZ (IPV6_ADDR_LEN / sizeof(uint32)) +#else +#define IPADDR_U32_SZ 1 +#endif + +struct ctf_conn_tuple { + uint32 sip[IPADDR_U32_SZ], dip[IPADDR_U32_SZ]; + uint16 sp, dp; + uint8 proto; +}; + +typedef struct ctf_nat { + uint32 ip; + uint16 port; +} ctf_nat_t; + +#ifdef BCMFA +#define CTF_FA_PEND_ADD_ENTRY 0x1 +#define CTF_FA_ADD_ISPEND(ipc) ((ipc)->flags & CTF_FA_PEND_ADD_ENTRY) +#define CTF_FA_SET_ADD_PEND(ipc) ((ipc)->flags |= CTF_FA_PEND_ADD_ENTRY) +#define CTF_FA_CLR_ADD_PEND(ipc) ((ipc)->flags &= ~(CTF_FA_PEND_ADD_ENTRY)) +#endif /* BCMFA */ + +struct ctf_ipc { + struct ctf_ipc *next; /* Pointer to ipc entry */ + ctf_conn_tuple_t tuple; /* Tuple to uniquely id the flow */ + uint16 vid; /* VLAN id to use on txif */ + struct ether_addr dhost; /* Destination MAC address */ + struct ether_addr shost; /* Source MAC address */ + void *txif; /* Target interface to send */ + void *txbif; /* Target Bridge interface to send */ + uint32 action; /* NAT and/or VLAN actions */ + ctf_brc_t *brcp; /* BRC entry corresp to source mac */ + uint32 live; /* Counter used to expire the entry */ + struct ctf_nat nat; /* Manip data for SNAT, DNAT */ + struct ether_addr sa; /* MAC address of sender */ + uint8 tos; /* IPv4 tos or IPv6 traff class excl ECN */ + uint16 pppoe_sid; /* PPPOE session to use */ +#if defined(CTF_PPTP) || defined(CTF_L2TP) + void *pppox_opt; +#endif /* CTF_PPTP || CTF_L2TP */ + void *ppp_ifp; /* PPP interface handle */ + uint32 hits; /* Num frames matching ipc entry */ + uint64 *bytecnt_ptr; /* Pointer to the byte counter */ + struct ctf_mark mark; /* Mark value to use for the connection */ +#ifdef BCMFA + void *rxif; /* Receive interface */ + void *pkt; /* Received packet */ + uint8 flags; /* Flags for multiple purpose */ +#endif /* BCMFA */ + /* For broadstream iqos, counter is increased by ipc_tcp_susp or ipc_udp_susp */ + int susp_cnt; +}; + +struct ctf_ppp_sk { + struct pppox_sock *po; /* pointer to pppoe socket */ + unsigned char pppox_protocol; /* 0:pppoe/1:l2tp/ 2:pptp */ + struct ether_addr dhost; /* Remote MAC addr of host the pppox socket is bound to */ +}; + +typedef struct ctf_ppp { + struct ctf_ppp_sk psk; + unsigned short pppox_id; /* PPTP peer call id if wan type is pptp */ + /* PPPOE session ID if wan type is PPPOE */ +} ctf_ppp_t; + +#ifdef CTF_PPTP +/* PPTP */ +typedef struct ctf_pppopptp { + uint8 sk_pmtudisc; /* iph->frag_off */ + uint32 rt_dst_mtrc_lock_fgoff; /* iph->frag_off */ + uint32 rt_dst_mtrc_hoplmt; /* iph->ttl */ +} ctf_pppopptp_t; +#endif /* CTF_PPTP */ + +#ifdef CTF_L2TP +/* L2TP */ +struct ctf_pppol2tp_inet { + uint32 saddr; /* src IP address of tunnel */ + uint32 daddr; /* src IP address of tunnel */ + uint16 sport; /* src port */ + uint16 dport; /* dst port */ + uint8 tos; /* IP tos */ + uint8 ttl; +}; + +struct ctf_pppol2tp_session +{ + uint16 optver; + uint32 l2tph_len; + uint32 tunnel_id; + uint32 session_id; + uint32 peer_tunnel_id; + uint32 peer_session_id; +}; + +#endif /* CTF_L2TP */ + +extern ctf_t *ctf_kattach(osl_t *osh, uint8 *name); +extern void ctf_kdetach(ctf_t *kci); +extern ctf_attach_t ctf_attach_fn; +extern ctf_t *_ctf_attach(osl_t *osh, uint8 *name, uint32 *msg_level, + ctf_detach_cb_t cb, void *arg); +extern ctf_t *kcih; + +/* Hot bridge cache lkup */ +#define MAXBRCHOT 256 +#define MAXBRCHOTIF 4 +#define CTF_BRC_HOT_HASH(da) ((((uint8 *)da)[4] ^ ((uint8 *)da)[5]) & (MAXBRCHOT - 1)) +#define CTF_HOTBRC_CMP(hbrc, da, rxifp) \ +({ \ + ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(da); \ + ((eacmp((bh)->ea.octet, (da)) == 0) && (bh->brcp->txifp != (rxifp))); \ +}) + +/* Header prep for packets matching hot bridge cache entry */ +#define CTF_HOTBRC_L2HDR_PREP(osh, hbrc, prio, data, p) \ +do { \ + uint8 *l2h; \ + ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(data); \ + ASSERT(*(uint16 *)((data) + VLAN_TPID_OFFSET) == HTON16(ETHER_TYPE_8021Q)); \ + if (bh->brcp->action & CTF_ACTION_UNTAG) { \ + /* Remove vlan header */ \ + l2h = PKTPULL((osh), (p), VLAN_TAG_LEN); \ + ether_rcopy(l2h - VLAN_TAG_LEN + ETHER_ADDR_LEN, \ + l2h + ETHER_ADDR_LEN); \ + ether_rcopy(l2h - VLAN_TAG_LEN, l2h); \ + } else { \ + /* Update vlan header */ \ + l2h = (data); \ + *(uint16 *)(l2h + VLAN_TCI_OFFSET) = \ + HTON16((prio) << VLAN_PRI_SHIFT | bh->brcp->vid); \ + } \ +} while (0) + +#define CTF_IS_PKTTOBR(p) PKTISTOBR(p) + +#endif /* _HNDCTF_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/emf/emf_cfg.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/emf/emf_cfg.h new file mode 100644 index 00000000000..5d8449c5421 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/emf/emf_cfg.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: emf_cfg.h 605730 2015-12-11 07:15:57Z $ + */ + +#ifndef _EMF_CFG_H_ +#define _EMF_CFG_H_ + +#define SUCCESS 0 +#define FAILURE -1 + +#define EMFCFG_MAX_ARG_SIZE 1024 + +#define EMFCFG_CMD_EMF_ENABLE 1 +#define EMFCFG_CMD_MFDB_ADD 2 +#define EMFCFG_CMD_MFDB_DEL 3 +#define EMFCFG_CMD_MFDB_CLEAR 4 +#define EMFCFG_CMD_MFDB_LIST 5 +#define EMFCFG_CMD_BR_ADD 6 +#define EMFCFG_CMD_BR_DEL 7 +#define EMFCFG_CMD_BR_LIST 8 +#define EMFCFG_CMD_IF_ADD 9 +#define EMFCFG_CMD_IF_DEL 10 +#define EMFCFG_CMD_IF_LIST 11 +#define EMFCFG_CMD_UFFP_ADD 12 +#define EMFCFG_CMD_UFFP_DEL 13 +#define EMFCFG_CMD_UFFP_LIST 14 +#define EMFCFG_CMD_RTPORT_ADD 15 +#define EMFCFG_CMD_RTPORT_DEL 16 +#define EMFCFG_CMD_RTPORT_LIST 17 +#define EMFCFG_CMD_EMF_STATS 18 +#define EMFCFG_CMD_MC_DATA_IND 19 + +#define EMFCFG_OPER_TYPE_GET 1 +#define EMFCFG_OPER_TYPE_SET 2 + +#define EMFCFG_STATUS_SUCCESS 1 +#define EMFCFG_STATUS_FAILURE 2 +#define EMFCFG_STATUS_CMD_UNKNOWN 3 +#define EMFCFG_STATUS_OPER_UNKNOWN 4 +#define EMFCFG_STATUS_INVALID_IF 5 + +typedef struct emf_cfg_request +{ + uint8 inst_id[16]; /* Bridge name as instance identifier */ + uint32 command_id; /* Command identifier */ + uint32 oper_type; /* Operation type: GET, SET */ + uint32 status; /* Command status */ + uint32 size; /* Size of the argument */ + /* Command arguments */ + uint8 arg[EMFCFG_MAX_ARG_SIZE]; +} emf_cfg_request_t; + +typedef struct emf_cfg_mfdb +{ + uint32 mgrp_ip; /* Multicast Group address */ + uint8 if_name[16]; /* Interface on which members are present */ + void *if_ptr; /* Interface pointer (kernel only) */ +} emf_cfg_mfdb_t; + +typedef struct emf_cfg_mfdb_list +{ + uint32 num_entries; /* Number of entries in MFDB */ + struct mfdb_entry + { + uint32 mgrp_ip; /* Multicast Group address */ + uint8 if_name[16]; /* Interface name */ + uint32 pkts_fwd; /* Number of packets forwarded */ + void *if_ptr; /* Interface pointer (kernel only) */ + } mfdb_entry[0]; +} emf_cfg_mfdb_list_t; + +typedef struct emf_cfg_if +{ + uint8 if_name[16]; /* Name of the interface */ +} emf_cfg_if_t; + +typedef struct emf_cfg_if_list +{ + uint32 num_entries; /* Number of entries in EMF if list */ + emf_cfg_if_t if_entry[0]; /* Interface entry data */ +} emf_cfg_if_list_t; + +typedef struct emf_cfg_uffp +{ + uint8 if_name[16]; /* Name of the interface */ + void *if_ptr; /* Interface pointer (kernel only) */ +} emf_cfg_uffp_t; + +typedef struct emf_cfg_uffp_list +{ + uint32 num_entries; /* Number of entries in UFFP list */ + emf_cfg_uffp_t uffp_entry[0]; /* Interface entry data */ +} emf_cfg_uffp_list_t; + +typedef struct emf_cfg_rtport +{ + uint8 if_name[16]; /* Name of the interface */ + void *if_ptr; /* Interface pointer (kernel only) */ +} emf_cfg_rtport_t; + +typedef struct emf_cfg_rtport_list +{ + uint32 num_entries; /* Number of entries in UFFP list */ + emf_cfg_rtport_t rtport_entry[0]; /* Interface entry data */ +} emf_cfg_rtport_list_t; + +/* + * Multicast Forwarding Layer Statistics + */ +typedef struct emf_stats +{ + uint32 igmp_frames; /* IGMP frames received */ + uint32 igmp_frames_fwd; /* IGMP membership quries received */ + uint32 igmp_frames_sentup; /* IGMP membership reports seen */ + uint32 igmp_frames_dropped; /* IGMP frames dropped */ + uint32 mcast_data_frames; /* Multicast data frames received */ + uint32 mcast_data_fwd; /* Multicast data frames forwarded */ + uint32 mcast_data_flooded; /* Multicast data frames flooded */ + uint32 mcast_data_sentup; /* Multicast data frames sent up */ + uint32 mcast_data_dropped; /* Multicast data frames dropped */ + uint32 mfdb_cache_hits; /* MFDB cache hits */ + uint32 mfdb_cache_misses; /* MFDB cache misses */ +} emf_stats_t; + +extern void emf_cfg_request_process(emf_cfg_request_t *cfg); + +#endif /* _EMF_CFG_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/emf/emfc_export.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/emf/emfc_export.h new file mode 100644 index 00000000000..f3dba55d09d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/emf/emfc_export.h @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: emfc_export.h 619841 2016-02-18 12:32:11Z $ + */ + +#ifndef _EMFC_EXPORT_H_ +#define _EMFC_EXPORT_H_ + +#include + +#define SUCCESS 0 +#define FAILURE -1 + +#define EMF_DROP 0 +#define EMF_FORWARD 1 +#define EMF_NOP 1 +#define EMF_TAKEN 2 +#define EMF_FLOOD 10 +#define EMF_SENDUP 11 +#define EMF_CONVERT_QUERY 12 + +#ifdef EMFDBG + +#define EMF_LOG_DEBUG (1 << 0) +#define EMF_LOG_ERROR (1 << 1) +#define EMF_LOG_WARN (1 << 2) +#define EMF_LOG_INFO (1 << 3) +#define EMF_LOG_MFDB (1 << 4) + +#define EMF_LOG_LVL (EMF_LOG_ERROR | \ + EMF_LOG_WARN | \ + EMF_LOG_DEBUG | \ + EMF_LOG_INFO | \ + EMF_LOG_MFDB) + +#if (EMF_LOG_LVL & EMF_LOG_DEBUG) +#define EMF_DEBUG(fmt, args...) printf("EMF_DEBUG: " fmt, ##args) +#else /* EMF_LOG_LVL & EMF_LOG_DEBUG */ +#define EMF_DEBUG(fmt, args...) +#endif /* EMF_LOG_LVL & EMF_LOG_DEBUG */ + +#if (EMF_LOG_LVL & EMF_LOG_ERROR) +#define EMF_ERROR(fmt, args...) printf("EMF_ERROR: " fmt, ##args) +#else /* EMF_LOG_LVL & EMF_LOG_ERROR */ +#define EMF_ERROR(fmt, args...) +#endif /* EMF_LOG_LVL & EMF_LOG_ERROR */ + +#if (EMF_LOG_LVL & EMF_LOG_WARN) +#define EMF_WARN(fmt, args...) printf("EMF_WARN.: " fmt, ##args) +#else /* EMF_LOG_LVL & EMF_LOG_WARN */ +#define EMF_WARN(fmt, args...) +#endif /* EMF_LOG_LVL & EMF_LOG_WARN */ + +#if (EMF_LOG_LVL & EMF_LOG_INFO) +#define EMF_INFO(fmt, args...) printf("EMF_INFO.: " fmt, ##args) +#else /* EMF_LOG_LVL & EMF_LOG_INFO */ +#define EMF_INFO(fmt, args...) +#endif /* EMF_LOG_LVL & EMF_LOG_INFO */ + +#if (EMF_LOG_LVL & EMF_LOG_MFDB) +#define EMF_MFDB(fmt, args...) printf("EMF_MFDB.: " fmt, ##args) +#else /* EMF_LOG_LVL & EMF_LOG_MFDB */ +#define EMF_MFDB(fmt, args...) +#endif /* EMF_LOG_LVL & EMF_LOG_MFDB */ + +#else /* EMFDBG */ + +#define EMF_DEBUG(fmt, args...) +#define EMF_ERROR(fmt, args...) printf(fmt, ##args) +#define EMF_WARN(fmt, args...) +#define EMF_INFO(fmt, args...) +#define EMF_MFDB(fmt, args...) + +#endif /* EMFDBG */ + +/* Function pointer declarations */ +typedef int32 (*forward_fn_ptr)(void *, void *, uint32, void *, int); +typedef void (*sendup_fn_ptr)(void *, void *); +typedef int32 (*hooks_register_fn_ptr)(void *); +typedef int32 (*hooks_unregister_fn_ptr)(void *); + +/* + * Snooper + */ +typedef struct emfc_snooper +{ + /* Input function called when an IGMP packet is received by + * EMFL. + */ + int32 (*input_fn)(struct emfc_snooper *snooper, void *ifp, + uint8 *iph, uint8 *igmph, bool rt_port); + + /* Function called when EMF is enabled */ + int32 (*emf_enable_fn)(struct emfc_snooper *snooper); + + /* Function called when EMF is disabled */ + int32 (*emf_disable_fn)(struct emfc_snooper *snooper); + + /* Function called when interface is deleted */ + int32 (*emf_ifp_del_fn)(struct emfc_snooper *snooper, void *ifp); + +#ifdef BCM_NBUFF_WLMCAST + int32 (*remove_sta_fn)(struct emfc_snooper *snooper, void *sta, uint32 src_ip); +#endif + +} emfc_snooper_t; + +/* + * Wrapper specific functions + */ +typedef struct emfc_wrapper +{ +#ifdef BCM_NBUFF_WLMCAST + void *(*hooks_get_fn)(int cmd, void *p, void *p1, void *p2); + int32 (*stall_sta_check_fn)(void *wrapper, void *p, uint32 mgrp_ip); + /* Function called to forward frames on a specific interface */ +#endif + int32 (*forward_fn)(void *wrapper, void *p, uint32 mgrp_ip, + void *txif, int rt_port); + /* Function called to send packet up the stack */ + void (*sendup_fn)(void *wrapper, void *p); + + /* Function called to register hooks into the bridge */ + int32 (*hooks_register_fn)(void *wrapper); + + /* Function called to unregister hooks into the bridge */ + int32 (*hooks_unregister_fn)(void *wrapper); + + /* Function called when mfdb entry is being added */ + int32 (*mfdb_add_fn)(void *wrapper, uint32 mgrp_ip, void *txif); + + /* Function called when mfdb entry is being deleted */ + int32 (*mfdb_delete_fn)(void *wrapper, uint32 mgrp_ip, void *txif); + +} emfc_wrapper_t; + +struct emfc_info; + +#if defined(BCM_NBUFF_WLMCAST_IPV6) +extern uint32 emfc_ipv6_input(struct emfc_info *emfc, void *sdu, void *ifp, + uint8 *iph, bool rt_port); +extern int32 emfc_mfdb_membership_status_change(struct emfc_info *emfc, + uint32 mgrp_ip, void *ifp, int is_valid); +extern int32 emfc_mfdb_ipv6_membership_del(struct emfc_info *emfc, void *mgrp_ip, void *ifp); +extern int32 emfc_mfdb_ipv6_membership_status_change(struct emfc_info *emfc, + void *mgrp_ip, void *ifp, int is_valid); +extern int32 emfc_mfdb_ipv6_membership_add(struct emfc_info *emfc, void *mgrp_ip, void *ifp); +extern int32 emfc_mfdb_ipv6_membership_dev_del(void *dev, void *grp, void *ifp); +#endif + +#ifdef BCM_NBUFF_WLMCAST +typedef struct { + void * p1; + void * p2; +} wmf_emf_pointers; +#define WL_AC_COUNT 4 /* Sync with wireless 802.11 AC_COUNT */ +#endif /* BCM_NBUFF_WLMCAST */ + +/* + * Description: This function is called from the OS specific module init + * routine to initialize the EMFL. This function primarily + * initializes the EMFL global data and MFDB. + * + * Input: inst_id - Instance identier used to associate EMF and + * IGMP snooper instances. + * emfi - EMFL OS Specific global data handle + * osh - OS abstraction layer handle + * wrapper - Wrapper specific info + * + * Return: emfc - EMFL Common code global instance handle + */ +extern struct emfc_info * emfc_init(int8 *inst_id, void *emfi, osl_t *osh, emfc_wrapper_t *wrapper); + +/* + * Description: This function is called from OS specific module exit + * routine. This routine primarily clears the MFDB and + * frees the EMF instance data. + * + * Input: emfc - EMFL Common code global instance handle + */ +extern void emfc_exit(struct emfc_info *emfc); + +/* + * Description: This function is called by the OS specific EMFL code + * for every frame seen at the bridge pre and ip post hook + * points. It calls the registered snooper input function + * if the received frame type is an IGMP frame. For multicast + * data frames it handles the frame forwarding. The frame + * forwarding is done based on the information stored in + * the MFDB. MFDB is updated by IGMP snooper module. + * + * Input: emfc - EMFL Common code Global instance handle + * sdu - Pointer to packet buffer. + * ifp - Interface on which the packet arrived. + * iph - Pointer to start of IP header. When IGMP + * frame is input, it is assumed that the IP + * header and IGMP header are contiguos. + * rt_port - TRUE when the packet is received from IP + * Stack, FALSE otherwise. + * + * Return: EMF_NOP - No processing needed by EMF, just return + * the packet back. + * EMF_TAKEN - EMF has taken the ownership of the packet. + * EMF_DROP - Indicates the packet should be dropped. + */ +extern uint32 emfc_input(struct emfc_info *emfc, void *sdu, void *ifp, + uint8 *iph, bool rt_port); + +/* + * Description: This function is called to add MFDB entry. Each MFDB entry + * contains the multicast group address and list of interfaces + * that has participating group members. The caller of the + * function needs to make sure to delete the entry as many + * times as add is done. + * + * Input: emfc - EMFL Common code global instance handle + * mgrp_ip - Multicast group IP address of the entry. + * ifp - Pointer to the interface on which the member + * is present. + * + * Return: SUCCESS or FAILURE + */ +extern int32 emfc_mfdb_membership_add(struct emfc_info *emfc, uint32 mgrp_ip, void *ifp); + +/* + * Description: This function is called by the IGMP snooper layer to delete + * the MFDB entry. It deletes the group entry also if the + * interface entry is last in the group. + * + * Input: Same as above function. + * + * Return: SUCCESS or FAILURE + */ +extern int32 emfc_mfdb_membership_del(struct emfc_info *emfc, uint32 mgrp_ip, void *ifp); + +/* + * Description: This function is called by the IGMP snooper layer to + * register snooper instance with EMFL. + * + * Input: inst_id - Instance identier used to associate EMF + * and IGMP snooper instances. + * emfc - EMFL Common code global instance handle + * snooper - Contains snooper specific parameters and + * event callback functions. These functions + * are called by EMFL on events like IGMP + * packet receive, EMF enable and disable. + * The snooper parameter needs to global. + * + * Return: SUCCESS or FAILURE + */ +extern int32 emfc_igmp_snooper_register(int8 *inst_id, struct emfc_info **emfc, + emfc_snooper_t *snooper); + +/* + * Description: This function is called by the IGMP snooper layer to + * unregister snooper instance. + * + * Input: handle - Handle returned during registration. + * snooper - Same as above. + */ +extern void emfc_igmp_snooper_unregister(struct emfc_info *emfc); + +/* + * Description: This function is called from the OS Specific layer when + * user issues a configuration command. + * + * Input: emfc - EMFL Common code global instance handle + * + * Input/Output: cfg - Pointer to configuration request data. It + * contains the command id, operation type, + * corresponding arguments and output status. + */ +extern void emfc_cfg_request_process(struct emfc_info *emfc, emf_cfg_request_t *cfg); + +/* + * Description: This function is called from OS specific module init + * routine. It allocates global resources required by the + * common code. + * + * Return: SUCCESS or FAILURE + */ +extern int32 emfc_module_init(void); + +/* + * Description: This function is called from OS specific module cleanup + * routine. It frees all the global resources. + */ +extern void emfc_module_exit(void); + +/* + * Description: This function is called by the IGMP Snooper to add a Router + * Port. Router Port is the interface on which the IGMP Snooper + * determines that a multicast router is present. We set a bit + * in the flag field of the interface list entry to mark it as + * router port. + * + * Input: emfc - EMFC Global Instance handle + * ifp - Interface pointer + * + * Return: SUCCESS or FAILURE + */ +extern int32 emfc_rtport_add(struct emfc_info *emfc, void *ifp); + +/* + * Description: This function is called by the IGMP Snooper to delete a + * Router Port. We clear the corresponding bit in the flags + * field to mark the port as non-router port. + * + * Input: emfc - EMFC Global Instance handle + * ifp - Interface pointer + * + * Return: SUCCESS or FAILURE + */ +extern int32 emfc_rtport_del(struct emfc_info *emfc, void *ifp); + +/* + * Description: This function is called by OS Specific layer when user issues + * configuration command to add an interface. It adds an entry to + * the global interface list maintained by EMFC. + * + * Input: emfc - EMFC Global Instance handle + * ifp - Interface pointer + */ +extern int32 emfc_iflist_add(struct emfc_info *emfc, void *ifp); + +/* + * Description: This function is called by OS Specific layer when user issues + * configuration command to delete an interface. It removes an + * entry from the global interface list maintained by EMFC. + * + * Input: emfc - EMFC Global Instance handle + * ifp - Interface pointer + */ +extern int32 emfc_iflist_del(struct emfc_info *emfc, void *ifp); + +#endif /* _EMFC_EXPORT_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/igs/igs_cfg.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/igs/igs_cfg.h new file mode 100644 index 00000000000..162155b3e12 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/igs/igs_cfg.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: igs_cfg.h $ + */ + +#ifndef _IGS_CFG_H_ +#define _IGS_CFG_H_ + +#if defined(BCM_NBUFF_WLMCAST_IPV6) +#include +#endif +#define SUCCESS 0 +#define FAILURE -1 + +#define IGSCFG_MAX_ARG_SIZE 1024 + +#define IGSCFG_CMD_BR_ADD 1 +#define IGSCFG_CMD_BR_DEL 2 +#define IGSCFG_CMD_BR_LIST 3 +#define IGSCFG_CMD_IGSDB_LIST 4 +#define IGSCFG_CMD_RTPORT_LIST 5 +#define IGSCFG_CMD_IGS_STATS 6 +#if defined(BCM_NBUFF_WLMCAST_IPV6) +#define IGSCFG_CMD_IGSDB_LIST_IPV6 7 +#define IGSCFG_CMD_IGS_STATS_IPV6 8 +#endif + +#define IGSCFG_OPER_TYPE_GET 1 +#define IGSCFG_OPER_TYPE_SET 2 + +#define IGSCFG_STATUS_SUCCESS 1 +#define IGSCFG_STATUS_FAILURE 2 +#define IGSCFG_STATUS_CMD_UNKNOWN 3 +#define IGSCFG_STATUS_OPER_UNKNOWN 4 +#define IGSCFG_STATUS_INVALID_IF 5 + +typedef struct igs_cfg_request +{ + uint8 inst_id[16]; /* Bridge name as instance id */ + uint32 command_id; /* Command identifier */ + uint32 oper_type; /* Operation type: GET, SET */ + uint32 status; /* Command status */ + uint32 size; /* Size of the argument */ + uint8 arg[IGSCFG_MAX_ARG_SIZE]; /* Command arguments */ +} igs_cfg_request_t; + +typedef struct igs_cfg_sdb_list +{ + uint32 num_entries; /* Num of entries in IGSDB */ + struct sdb_entry + { +#if defined(BCM_NBUFF_WLMCAST_IPV6) + union { + uint32 mgrp_ip; /* Multicast group address */ + struct ipv6_addr mgrp_ipv6; + }; + union { + uint32 mh_ip; /* Member IP address */ + struct ipv6_addr mh_ipv6; + }; +#else + uint32 mgrp_ip; /* Multicast group address */ + uint32 mh_ip; /* Member IP address */ +#endif + uint8 if_name[16]; /* Interface member is present */ + } sdb_entry[0]; +} igs_cfg_sdb_list_t; + +typedef struct igs_cfg_rtport +{ + uint32 mr_ip; /* IP address of mcast router */ + uint8 if_name[16]; /* Name of the interface */ +} igs_cfg_rtport_t; + +typedef struct igs_cfg_rtport_list +{ + uint32 num_entries; /* Number of entries in RTPORT list */ + igs_cfg_rtport_t rtport_entry[0]; /* Interface entry data */ +} igs_cfg_rtport_list_t; + +/* + * IGMP Snooping Layer Statistics + */ +typedef struct igs_stats +{ + uint32 igmp_packets; /* IGMP packets received */ + uint32 igmp_queries; /* IGMP membership quries received */ + uint32 igmp_reports; /* IGMP membership reports */ + uint32 igmp_v2reports; /* IGMP v2 membership reports */ + uint32 igmp_leaves; /* IGMP membership leaves */ + uint32 igmp_not_handled; /* IGMP frames not handled */ + uint32 igmp_mem_timeouts; /* IGMP membership timeouts */ + uint32 igmp_frames_fwd; /* IGMP membership quries received */ + uint32 igmp_frames_sentup; /* IGMP membership reports seen */ + uint32 igmp_mcast_groups; /* Current total of mcast groups */ + uint32 igmp_mcast_members; /* Current total of mcast members */ + uint32 igmp_missed_report_to; /* Missed membership report TO count */ +} igs_stats_t; + +extern void igs_cfg_request_process(igs_cfg_request_t *cfg); + +#endif /* _IGS_CFG_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/igs/igsc_export.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/igs/igsc_export.h new file mode 100644 index 00000000000..bd1172c9f2d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/emf/igs/igsc_export.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: igsc_export.h 605730 2015-12-11 07:15:57Z $ + */ + +#ifndef _IGSC_EXPORT_H_ +#define _IGSC_EXPORT_H_ + +#ifdef IGSDBG + +#define IGS_LOG_DEBUG (1 << 0) +#define IGS_LOG_ERROR (1 << 1) +#define IGS_LOG_WARN (1 << 2) +#define IGS_LOG_INFO (1 << 3) +#define IGS_LOG_IGSDB (1 << 4) + +#define IGS_LOG_LVL (IGS_LOG_ERROR | \ + IGS_LOG_WARN | \ + IGS_LOG_DEBUG | \ + IGS_LOG_INFO | \ + IGS_LOG_IGSDB) + +#if (IGS_LOG_LVL & IGS_LOG_DEBUG) +#define IGS_DEBUG(fmt, args...) printf("IGS_DEBUG: " fmt, ##args) +#else /* IGS_LOG_LVL & IGS_LOG_DEBUG */ +#define IGS_DEBUG(fmt, args...) +#endif /* IGS_LOG_LVL & IGS_LOG_DEBUG */ + +#if (IGS_LOG_LVL & IGS_LOG_ERROR) +#define IGS_ERROR(fmt, args...) printf("IGS_ERROR: " fmt, ##args) +#else /* IGS_LOG_LVL & IGS_LOG_ERROR */ +#define IGS_ERROR(fmt, args...) +#endif /* IGS_LOG_LVL & IGS_LOG_ERROR */ + +#if (IGS_LOG_LVL & IGS_LOG_WARN) +#define IGS_WARN(fmt, args...) printf("IGS_WARN.: " fmt, ##args) +#else /* IGS_LOG_LVL & IGS_LOG_WARN */ +#define IGS_WARN(fmt, args...) +#endif /* IGS_LOG_LVL & IGS_LOG_WARN */ + +#if (IGS_LOG_LVL & IGS_LOG_INFO) +#define IGS_INFO(fmt, args...) printf("IGS_INFO.: " fmt, ##args) +#else /* IGS_LOG_LVL & IGS_LOG_INFO */ +#define IGS_INFO(fmt, args...) +#endif /* IGS_LOG_LVL & IGS_LOG_INFO */ + +#if (IGS_LOG_LVL & IGS_LOG_IGSDB) +#define IGS_IGSDB(fmt, args...) printf("IGS_IGSDB: " fmt, ##args) +#else /* IGS_LOG_LVL & IGS_LOG_IGSDB */ +#define IGS_IGSDB(fmt, args...) +#endif /* IGS_LOG_LVL & IGS_LOG_IGSDB */ + +#else /* IGSDBG */ + +#define IGS_DEBUG(fmt, args...) +#define IGS_ERROR(fmt, args...) printf(fmt, ##args) +#define IGS_WARN(fmt, args...) +#define IGS_INFO(fmt, args...) +#define IGS_IGSDB(fmt, args...) + +#endif /* IGSDBG */ + +typedef int32 (*igs_broadcast_fn_ptr)(void *wrapper, uint8 *ip, uint32 length, uint32 mgrp_ip); + +/* + * Wrapper specific functions + */ +typedef struct igsc_wrapper +{ + + /* Function called to broadcast IGMP query */ + int32 (*igs_broadcast)(void *wrapper, uint8 *ip, uint32 length, uint32 mgrp_ip); +#if defined(BCM_NBUFF_WLMCAST_IPV6) + int cmdline_indicator; /* indicate igsc_info created from cmdline or not */ +#endif + +} igsc_wrapper_t; + +struct igsc_info; + +/* + * Description: This function is called from the OS specific module init + * routine to initialize the IGSL. This function primarily + * initializes the IGMP Snooping Layer global (IGSL) data and + * IGSDB. It also associates the snooper instance with EMF + * instance. + * + * Input: inst_id - IGS instance identifier. + * igs_info - IGSL OS Specific global data handle + * osh - OS abstraction layer handle + * emf_handle - Handle to use when interfacing with EMF. + * wrapper - Wrapper spcific info. + * + * Return: igsc_info - IGSL Common code global data handle + */ +extern void * igsc_init(int8 *inst_id, void *igs_info, osl_t *osh, igsc_wrapper_t *wrapper); + +/* + * Description: This function is called from OS specific module exit routine + * This routine primarily stops the group interval timers, + * deletes and frees up the IGSDB entries. + * + * Input: igs_info - IGSL OS Specific global data handle + */ +extern void igsc_exit(struct igsc_info *igsc_info); + +/* + * Description: This function returns various packet counters and global + * stats of IGSL. It is called from the IGSL OS specific + * command handler. + * + * Input: igsc_info - IGSL Common code global instance handle + * size - Size of the input buffer. + * + * Output: stats - Pointer to structure of type igs_stats_t + * + * Return: SUCCESS or FAILURE. + */ +extern int32 igsc_stats_get(struct igsc_info *igsc_info, igs_stats_t *stats, uint32 size); + +/* + * Description: This function clears the group interval timers and + * deletes the group, host and interface entries of the + * IGSDB. + * + * Input: igs_info - IGSL OS Specific global data handle + */ +extern void igsc_sdb_clear(struct igsc_info *igsc_info); + +/* + * Description: This function is called to obtain the IGSDB entry list. + */ +extern int32 igsc_sdb_list(struct igsc_info *igsc_info, igs_cfg_sdb_list_t *list, uint32 size); + +#if defined(BCM_NBUFF_WLMCAST_IPV6) +extern int32 igsc_sdb_list_ipv6(struct igsc_info *igsc_info, igs_cfg_sdb_list_t *list, uint32 size); +#endif + +/* + * Description: This function is called from the OS Specific layer when + * user issues a configuration command. + * + * Input: igs_info - IGSC global instance handle + * + * Input/Output: cfg - Pointer to configuration request data. It + * contains the command id, operation type, + * corresponding arguments and output status. + */ +extern void igsc_cfg_request_process(struct igsc_info *igsc_info, igs_cfg_request_t *cfg); + +/* + * Description: This function is called to delete igsc sdb entries + * specific to an interface + * + * Input: igs_info - IGSC global instance handle + * ifp - Interface pointer + */ +extern int32 igsc_sdb_interface_del(struct igsc_info *igsc_info, void *ifp); + +/* + * Description: This function is called to delete igsc sdb rtport entries + * specific to an interface + * + * Input: igs_info - IGSC global instance handle + * ifp - Interface pointer + */ +extern int32 igsc_interface_rtport_del(struct igsc_info *igsc_info, void *ifp); + +#endif /* _IGSC_EXPORT_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/flash.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/flash.h new file mode 100644 index 00000000000..e2633352697 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/flash.h @@ -0,0 +1,300 @@ +/* + * flash.h: Common definitions for flash access. + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: flash.h 527388 2015-01-17 08:59:26Z $ + */ + +/* FILE-CSTYLED Cannot figure out how to make the initialization continuation lines acceptable */ + +/* Types of flashes we know about */ +typedef enum _flash_type {OLD, BSC, SCS, AMD, SST, SFLASH} flash_type_t; + +/* Commands to write/erase the flases */ +typedef struct _flash_cmds{ + flash_type_t type; + bool need_unlock; + uint16 pre_erase; + uint16 erase_block; + uint16 erase_chip; + uint16 write_word; + uint16 write_buf; + uint16 clear_csr; + uint16 read_csr; + uint16 read_id; + uint16 confirm; + uint16 read_array; +} flash_cmds_t; + +#define UNLOCK_CMD_WORDS 2 /* 2 words per command */ + +typedef struct _unlock_cmd { + uint addr[UNLOCK_CMD_WORDS]; + uint16 cmd[UNLOCK_CMD_WORDS]; +} unlock_cmd_t; + +/* Flash descriptors */ +typedef struct _flash_desc { + uint16 mfgid; /* Manufacturer Id */ + uint16 devid; /* Device Id */ + uint size; /* Total size in bytes */ + uint width; /* Device width in bytes */ + flash_type_t type; /* Device type old, S, J */ + uint bsize; /* Block size */ + uint nb; /* Number of blocks */ + uint ff; /* First full block */ + uint lf; /* Last full block */ + uint nsub; /* Number of subblocks */ + uint *subblocks; /* Offsets for subblocks */ + char *desc; /* Description */ +} flash_desc_t; + +#ifdef DECLARE_FLASHES +flash_cmds_t sflash_cmd_t = + { SFLASH, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +#ifdef CCNFLASH_SUPPORT +flash_cmds_t nflash_cmd_t = + { NFLASH, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +#endif /* CCNFLASH_SUPPORT */ + +flash_cmds_t flash_cmds[] = { +/* type needu preera eraseb erasech write wbuf clcsr rdcsr rdid + * confrm read + */ + { BSC, 0, 0x00, 0x20, 0x00, 0x40, 0x00, 0x50, 0x70, 0x90, + 0xd0, 0xff }, + { SCS, 0, 0x00, 0x20, 0x00, 0x40, 0xe8, 0x50, 0x70, 0x90, + 0xd0, 0xff }, + { AMD, 1, 0x80, 0x30, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x90, + 0x00, 0xf0 }, + { SST, 1, 0x80, 0x50, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x90, + 0x00, 0xf0 }, + { 0 } +}; + +unlock_cmd_t unlock_cmd_amd = { +#ifdef MIPSEB +#ifdef BCMHND74K +/* addr: */ { 0x0aac, 0x0552}, +#else /* !74K, bcm33xx */ +/* addr: */ { 0x0aa8, 0x0556}, +#endif /* BCMHND74K */ +#else +/* addr: */ { 0x0aaa, 0x0554}, +#endif +/* data: */ { 0xaa, 0x55} +}; + +unlock_cmd_t unlock_cmd_sst = { +#ifdef MIPSEB +#ifdef BCMHND74K +/* addr: */ { 0xaaac, 0x5552}, +#else /* !74K, bcm33xx */ +/* addr: */ { 0xaaa8, 0x5556}, +#endif /* BCMHND74K */ +#else +/* addr: */ { 0xaaaa, 0x5554}, +#endif +/* data: */ { 0xaa, 0x55} +}; + +#define AMD_CMD 0xaaa +#define SST_CMD 0xaaaa + +/* intel unlock block cmds */ +#define INTEL_UNLOCK1 0x60 +#define INTEL_UNLOCK2 0xD0 + +/* Just eight blocks of 8KB byte each */ + +uint blk8x8k[] = { + 0x00000000, + 0x00002000, + 0x00004000, + 0x00006000, + 0x00008000, + 0x0000a000, + 0x0000c000, + 0x0000e000, + 0x00010000 +}; + +/* Funky AMD arrangement for 29xx800's */ +uint amd800[] = { + 0x00000000, /* 16KB */ + 0x00004000, /* 32KB */ + 0x0000c000, /* 8KB */ + 0x0000e000, /* 8KB */ + 0x00010000, /* 8KB */ + 0x00012000, /* 8KB */ + 0x00014000, /* 32KB */ + 0x0001c000, /* 16KB */ + 0x00020000 +}; + +/* AMD arrangement for 29xx160's */ +uint amd4112[] = { + 0x00000000, /* 32KB */ + 0x00008000, /* 8KB */ + 0x0000a000, /* 8KB */ + 0x0000c000, /* 16KB */ + 0x00010000 +}; + +uint amd2114[] = { + 0x00000000, /* 16KB */ + 0x00004000, /* 8KB */ + 0x00006000, /* 8KB */ + 0x00008000, /* 32KB */ + 0x00010000 +}; + +flash_desc_t sflash_desc = + { 0, 0, 0, 0, SFLASH, 0, 0, 0, 0, 0, NULL, "SFLASH" }; + +#ifdef CCNFLASH_SUPPORT +flash_desc_t nflash_desc = + { 0, 0, 0, 0, NFLASH, 0, 0, 0, 0, 0, NULL, "NFLASH" }; +#endif /* CCNFLASH_SUPPORT */ + +flash_desc_t flashes[] = { + { 0x00b0, 0x00d0, 0x0200000, 2, SCS, 0x10000, 32, 0, 31, 0, NULL, + "Intel 28F160S3/5 1Mx16" }, + { 0x00b0, 0x00d4, 0x0400000, 2, SCS, 0x10000, 64, 0, 63, 0, NULL, + "Intel 28F320S3/5 2Mx16" }, + { 0x0089, 0x8890, 0x0200000, 2, BSC, 0x10000, 32, 0, 30, 8, blk8x8k, + "Intel 28F160B3 1Mx16 TopB" }, + { 0x0089, 0x8891, 0x0200000, 2, BSC, 0x10000, 32, 1, 31, 8, blk8x8k, + "Intel 28F160B3 1Mx16 BotB" }, + { 0x0089, 0x8896, 0x0400000, 2, BSC, 0x10000, 64, 0, 62, 8, blk8x8k, + "Intel 28F320B3 2Mx16 TopB" }, + { 0x0089, 0x8897, 0x0400000, 2, BSC, 0x10000, 64, 1, 63, 8, blk8x8k, + "Intel 28F320B3 2Mx16 BotB" }, + { 0x0089, 0x8898, 0x0800000, 2, BSC, 0x10000, 128, 0, 126, 8, blk8x8k, + "Intel 28F640B3 4Mx16 TopB" }, + { 0x0089, 0x8899, 0x0800000, 2, BSC, 0x10000, 128, 1, 127, 8, blk8x8k, + "Intel 28F640B3 4Mx16 BotB" }, + { 0x0089, 0x88C2, 0x0200000, 2, BSC, 0x10000, 32, 0, 30, 8, blk8x8k, + "Intel 28F160C3 1Mx16 TopB" }, + { 0x0089, 0x88C3, 0x0200000, 2, BSC, 0x10000, 32, 1, 31, 8, blk8x8k, + "Intel 28F160C3 1Mx16 BotB" }, + { 0x0089, 0x88C4, 0x0400000, 2, BSC, 0x10000, 64, 0, 62, 8, blk8x8k, + "Intel 28F320C3 2Mx16 TopB" }, + { 0x0089, 0x88C5, 0x0400000, 2, BSC, 0x10000, 64, 1, 63, 8, blk8x8k, + "Intel 28F320C3 2Mx16 BotB" }, + { 0x0089, 0x88CC, 0x0800000, 2, BSC, 0x10000, 128, 0, 126, 8, blk8x8k, + "Intel 28F640C3 4Mx16 TopB" }, + { 0x0089, 0x88CD, 0x0800000, 2, BSC, 0x10000, 128, 1, 127, 8, blk8x8k, + "Intel 28F640C3 4Mx16 BotB" }, + { 0x0089, 0x0014, 0x0400000, 2, SCS, 0x20000, 32, 0, 31, 0, NULL, + "Intel 28F320J5 2Mx16" }, + { 0x0089, 0x0015, 0x0800000, 2, SCS, 0x20000, 64, 0, 63, 0, NULL, + "Intel 28F640J5 4Mx16" }, + { 0x0089, 0x0016, 0x0400000, 2, SCS, 0x20000, 32, 0, 31, 0, NULL, + "Intel 28F320J3 2Mx16" }, + { 0x0089, 0x0017, 0x0800000, 2, SCS, 0x20000, 64, 0, 63, 0, NULL, + "Intel 28F640J3 4Mx16" }, + { 0x0089, 0x0018, 0x1000000, 2, SCS, 0x20000, 128, 0, 127, 0, NULL, + "Intel 28F128J3 8Mx16" }, + { 0x00b0, 0x00e3, 0x0400000, 2, BSC, 0x10000, 64, 1, 63, 8, blk8x8k, + "Sharp 28F320BJE 2Mx16 BotB" }, + { 0x0001, 0x224a, 0x0100000, 2, AMD, 0x10000, 16, 0, 13, 8, amd800, + "AMD 29DL800BT 512Kx16 TopB" }, + { 0x0001, 0x22cb, 0x0100000, 2, AMD, 0x10000, 16, 2, 15, 8, amd800, + "AMD 29DL800BB 512Kx16 BotB" }, + { 0x0001, 0x22c4, 0x0200000, 2, AMD, 0x10000, 32, 0, 30, 4, amd4112, + "AMD 29W160ET 1Mx16 TopB" }, + { 0x0001, 0x2249, 0x0200000, 2, AMD, 0x10000, 32, 1, 31, 4, amd2114, + "AMD 29lv160DB 1Mx16 BotB" }, + { 0x0001, 0x22f6, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 8, blk8x8k, + "AMD 29LV320DT 2Mx16 TopB" }, + { 0x0001, 0x22f9, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "AMD 29lv320DB 2Mx16 BotB" }, + { 0x0001, 0x00f9, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "AMD 29lv320DB 2Mx16 BotB in BYTE mode" }, + { 0x0001, 0x0201, 0x0800000, 2, AMD, 0x10000, 128, 1, 126, 8, blk8x8k, + "AMD 29DL640D 4Mx16" }, + { 0x0001, 0x1200, 0x01000000, 2, AMD, 0x10000, 256, 0, 255, 0, NULL, + "AMD 29LV128MH/L 8Mx16" }, + { 0x0001, 0x1301, 0x0800000, 2, AMD, 0x10000, 128, 0, 127, 0, NULL, + "AMD 29LV641MT 4Mx16" }, + { 0x0001, 0x1a01, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 8, blk8x8k, + "AMD 29lv320MT 2Mx16 TopB" }, + { 0x0001, 0x1a00, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "AMD 29lv320MB 2Mx16 BotB" }, + { 0x0001, 0x1001, 0x0800000, 2, AMD, 0x10000, 128, 0, 126, 8, blk8x8k, + "Spansion S29GL064A-R3 4Mx16 TopB" }, + { 0x0001, 0x1000, 0x0800000, 2, AMD, 0x10000, 128, 1, 127, 8, blk8x8k, + "Spansion S29GL064A-R4 4Mx16 BotB" }, + { 0x0001, 0x0c01, 0x0800000, 2, AMD, 0x10000, 128, 0, 127, 0, NULL, + "Spansion S29GL640A 8Mx16" }, + { 0x0001, 0x2201, 0x2000000, 2, AMD, 0x20000, 256, 0, 255, 0, NULL, + "Spansion S29GL256P 16Mx16" }, + { 0x0020, 0x22CA, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, + "ST 29w320DT 2Mx16 TopB" }, + { 0x0020, 0x22CB, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, + "ST 29w320DB 2Mx16 BotB" }, + { 0x0020, 0x22c4, 0x0200000, 2, AMD, 0x10000, 32, 0, 30, 4, amd4112, + "ST 29w160ET 1Mx16 TopB" }, + { 0x0020, 0x2249, 0x0200000, 2, AMD, 0x10000, 32, 1, 31, 4, amd2114, + "ST 29w160ET 1Mx16 BotB" }, + { 0x0020, 0x225d, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "ST M29DW324DB 2Mx16 TopB" }, + { 0x007f, 0x22f9, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "EON 29LV320CB 2Mx16 BotB" }, + { 0x00C2, 0x22c4, 0x0200000, 2, AMD, 0x10000, 32, 0, 30, 4, amd4112, + "MX 29LV160CT 1Mx16 TopB" }, + { 0x00C2, 0x2249, 0x0200000, 2, AMD, 0x10000, 32, 1, 31, 4, amd2114, + "MX 29LV160CB 1Mx16 BotB" }, + { 0x00C2, 0x22a8, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "MX 29LV320CB 2Mx16 BotB" }, + { 0x00C2, 0x00A7, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, + "MX29LV320T 2Mx16 TopB" }, + { 0x00C2, 0x00A8, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, + "MX29LV320B 2Mx16 BotB" }, + { 0x0004, 0x22F6, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, + "MBM29LV320TE 2Mx16 TopB" }, + { 0x0004, 0x22F9, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, + "MBM29LV320BE 2Mx16 BotB" }, + { 0x0098, 0x009A, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, + "TC58FVT321 2Mx16 TopB" }, + { 0x0098, 0x009C, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, + "TC58FVB321 2Mx16 BotB" }, + { 0x00C2, 0x22A7, 0x0400000, 2, AMD, 0x10000, 64, 0, 62, 4, amd4112, + "MX29LV320T 2Mx16 TopB" }, + { 0x00C2, 0x22A8, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 4, amd2114, + "MX29LV320B 2Mx16 BotB" }, + { 0x00BF, 0x2783, 0x0400000, 2, SST, 0x10000, 64, 0, 63, 0, NULL, + "SST39VF320 2Mx16" }, + { 0x00ec, 0x22e2, 0x0800000, 2, AMD, 0x10000, 128, 1, 127, 8, blk8x8k, + "Samsung K8D631UB 4Mx16 BotB" }, + { 0xddda, 0x0a00, 0x0400000, 2, AMD, 0x10000, 64, 1, 63, 8, blk8x8k, + "Samsung K8D631UB 4Mx16 BotB" }, + { 0, 0, 0, 0, OLD, 0, 0, 0, 0, 0, NULL, + NULL }, +}; + +#else /* !DECLARE_FLASHES */ + +extern flash_cmds_t flash_cmds[]; +extern unlock_cmd_t unlock_cmd; +extern flash_desc_t flashes[]; + +#endif /* DECLARE_FLASHES */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/hndnand.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/hndnand.h new file mode 100644 index 00000000000..34d5b762680 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/hndnand.h @@ -0,0 +1,139 @@ +/* + * Broadcom chipcommon NAND flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: hndnand.h 615704 2016-01-28 09:58:26Z $ + */ + +#ifndef _hndnand_h_ +#define _hndnand_h_ + +#define NFL_VENDOR_AMD 0x01 +#define NFL_VENDOR_NUMONYX 0x20 +#define NFL_VENDOR_MICRON 0x2C +#define NFL_VENDOR_TOSHIBA 0x98 +#define NFL_VENDOR_HYNIX 0xAD +#define NFL_VENDOR_SAMSUNG 0xEC +#define NFL_VENDOR_ESMT 0x92 +#define NFL_VENDOR_MXIC 0xC2 +#define NFL_VENDOR_ZENTEL_ESMT 0xC8 +#define NFL_VENDOR_WINBOND 0xEF + +#define NFL_SECTOR_SIZE 512 +#define NFL_TABLE_END 0xffffffff + +#define NFL_BOOT_SIZE 0x200000 +#define NFL_BOOT_OS_SIZE 0x2000000 +#define NFL_BBT_SIZE 0x100000 + +#ifdef __ARM_ARCH_7A__ +#define NFL_BIG_BOOT_SIZE 0x800000 /* 8 MB */ +#define NFL_BIG_BOOT_OS_SIZE 0x2600000 /* 38 MB */ +#define NFL_1M_BLOCK_SIZE 1024 /* KB */ + +#define nfl_boot_size(nfl) ((((nfl)->blocksize >> 10) >= NFL_1M_BLOCK_SIZE) ? \ + NFL_BIG_BOOT_SIZE : NFL_BOOT_SIZE) +#define nfl_boot_os_size(nfl) ((((nfl)->blocksize >> 10) >= NFL_1M_BLOCK_SIZE) ? \ + NFL_BIG_BOOT_OS_SIZE : NFL_BOOT_OS_SIZE) +#else +#define nfl_boot_size(nfl) NFL_BOOT_SIZE +#define nfl_boot_os_size(nfl) NFL_BOOT_OS_SIZE +#endif /* __ARM_ARCH_7A__ */ + +#ifndef _CFE_ +/* Command functions commands */ +#define CMDFUNC_ERASE1 1 +#define CMDFUNC_ERASE2 2 +#define CMDFUNC_SEQIN 3 +#define CMDFUNC_READ 4 +#define CMDFUNC_RESET 5 +#define CMDFUNC_READID 6 +#define CMDFUNC_STATUS 7 +#define CMDFUNC_READOOB 8 +#endif /* !_CFE_ */ + +struct hndnand; +typedef struct hndnand hndnand_t; + +struct hndnand { + uint blocksize; /* Block size */ + uint pagesize; /* Page size */ + uint oobsize; /* OOB size per page */ + uint numblocks; /* Number of blocks */ + uint32 type; /* Type */ + uint size; /* Total size in Mbytes */ + uint8 id[8]; + uint32 base; + uint32 phybase; + + uint sectorsize; /* 512 or 1K */ + uint sparesize; /* Spare size per sector */ + uint eccbytes; /* ECC code bytes per sector */ + uint ecclevel0; /* ECC algorithm for blocks 0 */ + uint ecclevel; /* ECC algorithm for blocks other than block 0 */ + uint32 chipidx; /* Current active chip index */ + uint32 width; /* Device width 0/1 => 8/16 bit */ + + si_t *sih; + void *core; + void *wrap; + void (*enable)(hndnand_t *nfl, int enable); + int (*read)(hndnand_t *nfl, uint64 offset, uint len, uchar *buf); + int (*write)(hndnand_t *nfl, uint64 offset, uint len, const uchar *buf); + int (*erase)(hndnand_t *nfl, uint64 offset); + int (*checkbadb)(hndnand_t *nfl, uint64 offset); + int (*markbadb)(hndnand_t *nfl, uint64 offset); + +#ifndef _CFE_ + int (*dev_ready)(hndnand_t *nfl); + int (*select_chip)(hndnand_t *nfl, int chip); + int (*cmdfunc)(hndnand_t *nfl, uint64 addr, int cmd); + int (*waitfunc)(hndnand_t *nfl, int *status); + int (*read_oob)(hndnand_t *nfl, uint64 addr, uint8 *oob); + int (*write_oob)(hndnand_t *nfl, uint64 addr, uint8 *oob); + int (*read_page)(hndnand_t *nfl, uint64 addr, uint8 *buf, uint8 *oob, bool ecc, + uint32 *herr, uint32 *serr); + int (*write_page)(hndnand_t *nfl, uint64 addr, const uint8 *buf, uint8 *oob, bool ecc); + int (*cmd_read_byte)(hndnand_t *nfl, int cmd, int arg); +#endif /* !_CFE_ */ +}; + +hndnand_t *hndnand_init(si_t *sih); +void hndnand_enable(hndnand_t *nfl, int enable); +int hndnand_read(hndnand_t *nfl, uint64 offset, uint len, uchar *buf); +int hndnand_write(hndnand_t *nfl, uint64 offset, uint len, const uchar *buf); +int hndnand_erase(hndnand_t *nfl, uint64 offset); +int hndnand_checkbadb(hndnand_t *nfl, uint64 offset); +int hndnand_mark_badb(hndnand_t *nfl, uint64 offset); + +#ifndef _CFE_ +int hndnand_dev_ready(hndnand_t *nfl); +int hndnand_select_chip(hndnand_t *nfl, int chip); +int hndnand_devcie_width(hndnand_t *nfl, int chip); +int hndnand_cmdfunc(hndnand_t *nfl, uint64 addr, int cmd); +int hndnand_waitfunc(hndnand_t *nfl, int *status); +int hndnand_read_oob(hndnand_t *nfl, uint64 addr, uint8 *oob); +int hndnand_write_oob(hndnand_t *nfl, uint64 addr, uint8 *oob); +int hndnand_read_page(hndnand_t *nfl, uint64 addr, uint8 *buf, uint8 *oob, bool ecc, + uint32 *herr, uint32 *serr); +int hndnand_write_page(hndnand_t *nfl, uint64 addr, const uint8 *buf, uint8 *oob, bool ecc); +int hndnand_cmd_read_byte(hndnand_t *nfl, int cmd, int arg); +#endif /* !_CFE_ */ + +#endif /* _hndnand_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/hndsflash.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/hndsflash.h new file mode 100644 index 00000000000..e25e8daa5ff --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/hndsflash.h @@ -0,0 +1,59 @@ +/* + * Broadcom chipcommon sflash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: hndsflash.h 596126 2015-10-29 19:53:48Z $ + */ + +#ifndef _hndsflash_h_ +#define _hndsflash_h_ + +#include +#include + +struct hndsflash; +typedef struct hndsflash hndsflash_t; + +struct hndsflash { + uint blocksize; /* Block size */ + uint numblocks; /* Number of blocks */ + uint32 type; /* Type */ + uint size; /* Total size in bytes */ + uint32 base; + uint32 phybase; + uint8 vendor_id; + uint16 device_id; + + si_t *sih; + void *core; + int (*read)(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); + int (*write)(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); + int (*erase)(hndsflash_t *sfl, uint offset); + int (*commit)(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); + int (*poll)(hndsflash_t *sfl, uint offset); +}; + +hndsflash_t *hndsflash_init(si_t *sih); +int hndsflash_read(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); +int hndsflash_write(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); +int hndsflash_erase(hndsflash_t *sfl, uint offset); +int hndsflash_commit(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); +int hndsflash_poll(hndsflash_t *sfl, uint offset); + +#endif /* _hndsflash_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/nand_core.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/nand_core.h new file mode 100644 index 00000000000..91db9e5e56a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/nand_core.h @@ -0,0 +1,235 @@ +/* + * nand - Broadcom NAND specific definitions + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: nand_core.h 596126 2015-10-29 19:53:48Z $ + */ + +#ifndef _nand_core_h_ +#define _nand_core_h_ + +/* cpp contortions to concatenate w/arg prescan */ +#ifndef PAD +#define _PADLINE(line) pad ## line +#define _XSTR(line) _PADLINE(line) +#define PAD _XSTR(__LINE__) +#endif /* PAD */ + +typedef volatile struct nandregs { + uint32 revision; /* 0x000 */ + uint32 cmd_start; /* 0x004 */ + uint32 cmd_ext_address; /* 0x008 */ + uint32 cmd_address; /* 0x00c */ + uint32 cmd_end_address; /* 0x010 */ + uint32 intfc_status; /* 0x014 */ + uint32 cs_nand_select; /* 0x018 */ + uint32 cs_nand_xor; /* 0x01c */ + uint32 ll_op; /* 0x020 */ + uint32 mplane_base_ext_address; /* 0x024 */ + uint32 mplane_base_address; /* 0x028 */ + uint32 PAD[9]; /* 0x02C ~ 0x04C */ + + uint32 acc_control_cs0; /* 0x050 */ + uint32 config_cs0; /* 0x054 */ + uint32 timing_1_cs0; /* 0x058 */ + uint32 timing_2_cs0; /* 0x05c */ + uint32 acc_control_cs1; /* 0x060 */ + uint32 config_cs1; /* 0x064 */ + uint32 timing_1_cs1; /* 0x068 */ + uint32 timing_2_cs1; /* 0x06c */ + uint32 PAD[20]; /* 0x070 ~ 0x0bc */ + + uint32 corr_stat_threshold; /* 0x0c0 */ + uint32 PAD[1]; /* 0x0c4 */ + + uint32 blk_wr_protect; /* 0x0c8 */ + uint32 multiplane_opcodes_1; /* 0x0cc */ + uint32 multiplane_opcodes_2; /* 0x0d0 */ + uint32 multiplane_ctrl; /* 0x0d4 */ + uint32 PAD[9]; /* 0x0d8 ~ 0x0f8 */ + + uint32 uncorr_error_count; /* 0x0fc */ + uint32 corr_error_count; /* 0x100 */ + uint32 read_error_count; /* 0x104 */ + uint32 block_lock_status; /* 0x108 */ + uint32 ecc_corr_ext_addr; /* 0x10c */ + uint32 ecc_corr_addr; /* 0x110 */ + uint32 ecc_unc_ext_addr; /* 0x114 */ + uint32 ecc_unc_addr; /* 0x118 */ + uint32 flash_read_ext_addr; /* 0x11c */ + uint32 flash_read_addr; /* 0x120 */ + uint32 program_page_ext_addr; /* 0x124 */ + uint32 program_page_addr; /* 0x128 */ + uint32 copy_back_ext_addr; /* 0x12c */ + uint32 copy_back_addr; /* 0x130 */ + uint32 block_erase_ext_addr; /* 0x134 */ + uint32 block_erase_addr; /* 0x138 */ + uint32 inv_read_ext_addr; /* 0x13c */ + uint32 inv_read_addr; /* 0x140 */ + uint32 init_status; /* 0x144 */ + uint32 onfi_status; /* 0x148 */ + uint32 onfi_debug_data; /* 0x14c */ + uint32 semaphore; /* 0x150 */ + uint32 PAD[16]; /* 0x154 ~ 0x190 */ + + uint32 flash_device_id; /* 0x194 */ + uint32 flash_device_id_ext; /* 0x198 */ + uint32 ll_rddata; /* 0x19c */ + uint32 PAD[24]; /* 0x1a0 ~ 0x1fc */ + + uint32 spare_area_read_ofs[16]; /* 0x200 ~ 0x23c */ + uint32 PAD[16]; /* 0x240 ~ 0x27c */ + + uint32 spare_area_write_ofs[16]; /* 0x280 ~ 0x2bc */ + uint32 PAD[80]; /* 0x2c0 ~ 0x3fc */ + + uint32 flash_cache[128]; /* 0x400~0x5fc */ + uint32 PAD[576]; /* 0x600 ~ 0xefc */ + + uint32 direct_read_rd_miss; /* 0xf00 */ + uint32 block_erase_complete; /* 0xf04 */ + uint32 copy_back_complete; /* 0xf08 */ + uint32 program_page_complete; /* 0xf0c */ + uint32 no_ctlr_ready; /* 0xf10 */ + uint32 nand_rb_b; /* 0xf14 */ + uint32 ecc_mips_uncorr; /* 0xf18 */ + uint32 ecc_mips_corr; /* 0xf1c */ +} nandregs_t; + +/* nand cache size */ +#define NANDCACHE_SIZE 512 + +/* nand spare cache size */ +#define NANDSPARECACHE_SIZE 64 + +/* nand_cs_nand_select */ +#define NANDCSEL_NAND_WP 0x20000000 +#define NANDCSEL_AUTO_ID_CFG 0x40000000 + +/* nand_cmd_start commands */ +#define NANDCMD_NULL 0x00000000 +#define NANDCMD_PAGE_RD 0x01000000 +#define NANDCMD_SPARE_RD 0x02000000 +#define NANDCMD_STATUS_RD 0x03000000 +#define NANDCMD_PAGE_PROG 0x04000000 +#define NANDCMD_SPARE_PROG 0x05000000 +#define NANDCMD_COPY_BACK 0x06000000 +#define NANDCMD_ID_RD 0x07000000 +#define NANDCMD_BLOCK_ERASE 0x08000000 +#define NANDCMD_FLASH_RESET 0x09000000 +#define NANDCMD_LOCK 0x0a000000 +#define NANDCMD_LOCK_DOWN 0x0b000000 +#define NANDCMD_UNLOCK 0x0c000000 +#define NANDCMD_LOCK_STATUS 0x0d000000 +#define NANDCMD_PARAMETER_READ 0x0e000000 +#define NANDCMD_PARAMETER_CHANGE_COL 0x0f000000 +#define NANDCMD_LOW_LEVEL_OP 0x10000000 +#define NANDCMD_PAGE_READ_MULTI 0x11000000 +#define NANDCMD_STATUS_READ_MULTI 0x12000000 +#define NANDCMD_OPCODE_MASK 0x1f000000 + +/* nand_acc_control_cs0 */ +#define NANDAC_CS0_RD_ECC_EN 0x80000000 +#define NANDAC_CS0_WR_ECC_EN 0x40000000 +#define NANDAC_CS0_RD_ECC_BLK0_EN 0x20000000 +#define NANDAC_CS0_FAST_PGM_RDIN 0x10000000 +#define NANDAC_CS0_RD_ERASED_ECC_EN 0x08000000 +#define NANDAC_CS0_PARTIAL_PAGE_EN 0x04000000 +#define NANDAC_CS0_WR_PREEMPT_EN 0x02000000 +#define NANDAC_CS0_PAGE_HIT_EN 0x01000000 +#define NANDAC_CS0_PREFETCH_EN 0x00800000 +#define NANDAC_CS0_CACHE_MODE_EN 0x00400000 +#define NANDAC_CS0_CACHE_MODE_LAST_PAGE 0x00200000 +#define NANDAC_CS0_ECC_LEVEL_MASK 0x001f0000 +#define NANDAC_CS0_ECC_LEVEL_SHIFT 16 +#define NANDAC_CS0_ECC_LEVEL_20 0x00140000 +#define NANDAC_CS0_SECTOR_SIZE_1K 0x00000080 +#define NANDAC_CS0_SECTOR_SIZE_1K_SHIFT 7 +#define NANDAC_CS0_SPARE_AREA_SIZE 0x0000007f +#define NANDAC_CS0_SPARE_AREA_SHIFT 0 +#define NANDAC_CS0_SPARE_AREA_45B 0x0000002d + +/* nand_config_cs0 */ +#define NANDCF_CS0_CONFIG_LOCK 0x80000000 +#define NANDCF_CS0_BLOCK_SIZE_MASK 0x70000000 +#define NANDCF_CS0_BLOCK_SIZE_SHIFT 28 +#define NANDCF_CS0_BLOCK_SIZE_1MB 5 +#define NANDCF_CS0_DEVICE_SIZE_MASK 0x0f000000 +#define NANDCF_CS0_DEVICE_SIZE_SHIFT 24 +#define NANDCF_CS0_DEVICE_SIZE_8GB 11 +#define NANDCF_CS0_DEVICE_WIDTH 0x00800000 +#define NANDCF_CS0_PAGE_SIZE_MASK 0x00300000 +#define NANDCF_CS0_PAGE_SIZE_SHIFT 20 +#define NANDCF_CS0_FULL_ADDR_BYTES_MASK 0x00070000 +#define NANDCF_CS0_FULL_ADDR_BYTES_SHIFT 16 +#define NANDCF_CS0_COL_ADDR_BYTES_MASK 0x00007000 +#define NANDCF_CS0_COL_ADDR_BYTES_SHIFT 12 +#define NANDCF_CS0_BLK_ADDR_BYTES_MASK 0x00000700 +#define NANDCF_CS0_BLK_ADDR_BYTES_SHIFT 8 + +/* nand_intfc_status */ +#define NANDIST_CTRL_READY 0x80000000 +#define NANDIST_FLASH_READY 0x40000000 +#define NANDIST_CACHE_VALID 0x20000000 +#define NANDIST_SPARE_VALID 0x10000000 +#define NANDIST_ERASED 0x08000000 +#define NANDIST_STATUS 0x000000ff +#define NANDIST_STATUS_FAIL 0x00000001 + +/* cmd_ext_address */ +#define NANDCMD_CS_SEL_MASK 0x00070000 +#define NANDCMD_CS_SEL_SHIFT 16 +#define NANDCMD_EXT_ADDR_MASK 0x0000ffff + +/* nand_timing_1 */ +#define NANDTIMING1_TWP_MASK 0xf0000000 +#define NANDTIMING1_TWP_SHIFT 28 +#define NANDTIMING1_TWH_MASK 0x0f000000 +#define NANDTIMING1_TWH_SHIFT 24 +#define NANDTIMING1_TRP_MASK 0x00f00000 +#define NANDTIMING1_TRP_SHIFT 20 +#define NANDTIMING1_TREH_MASK 0x000f0000 +#define NANDTIMING1_TREH_SHIFT 16 +#define NANDTIMING1_TCS_MASK 0x0000f000 +#define NANDTIMING1_TCS_SHIFT 12 +#define NANDTIMING1_TCLH_MASK 0x00000f00 +#define NANDTIMING1_TCLH_SHIFT 8 +#define NANDTIMING1_TALH_MASK 0x000000f0 +#define NANDTIMING1_TALH_SHIFT 4 +#define NANDTIMING1_TADL_MASK 0x0000000f +#define NANDTIMING1_TADL_SHIFT 0 + +/* nand_timing_2 */ +#define NANDTIMING2_CLK_SEL_MASK 0x80000000 +#define NANDTIMING2_CLK_SEL_SHIFT 31 +#define NANDTIMING2_TWB_MASK 0x00000e00 +#define NANDTIMING2_TWB_SHIFT 9 +#define NANDTIMING2_TWHR_MASK 0x000001f0 +#define NANDTIMING2_TWHR_SHIFT 4 +#define NANDTIMING2_TREAD_MASK 0x0000000f +#define NANDTIMING2_TREAD_SHIFT 0 + +/* + * NAND IDM + */ +/* Core specific control flags */ +#define NAND_APB_LITTLE_ENDIAN 0x01000000 +#define NAND_RO_CTRL_READY 0x00000001 + +#endif /* _nand_core_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/nflash.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/nflash.h new file mode 100644 index 00000000000..8d7b0af1e81 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/nflash.h @@ -0,0 +1,88 @@ +/* + * Broadcom chipcommon NAND flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: nflash.h 667654 2016-10-28 02:10:45Z $ + */ + +#ifndef _nflash_h_ +#define _nflash_h_ + +/* nand_cmd_start commands */ +#define NCMD_NULL 0 +#define NCMD_PAGE_RD 1 +#define NCMD_SPARE_RD 2 +#define NCMD_STATUS_RD 3 +#define NCMD_PAGE_PROG 4 +#define NCMD_SPARE_PROG 5 +#define NCMD_COPY_BACK 6 +#define NCMD_ID_RD 7 +#define NCMD_BLOCK_ERASE 8 +#define NCMD_FLASH_RESET 9 +#define NCMD_LOCK 0xa +#define NCMD_LOCK_DOWN 0xb +#define NCMD_UNLOCK 0xc +#define NCMD_LOCK_STATUS 0xd + +/* nand_acc_control */ +#define NAC_RD_ECC_EN 0x80000000 +#define NAC_WR_ECC_EN 0x40000000 +#define NAC_RD_ECC_BLK0_EN 0x20000000 +#define NAC_FAST_PGM_RDIN 0x10000000 +#define NAC_RD_ERASED_ECC_EN 0x08000000 +#define NAC_PARTIAL_PAGE_EN 0x04000000 +#define NAC_PAGE_HIT_EN 0x01000000 +#define NAC_ECC_LEVEL0_MASK 0x00f00000 +#define NAC_ECC_LEVEL0_SHIFT 20 +#define NAC_ECC_LEVEL_MASK 0x000f0000 +#define NAC_ECC_LEVEL_SHIFT 16 +#define NAC_SPARE_SIZE0 0x00003f00 +#define NAC_SPARE_SIZE 0x0000003f + +/* nand_config */ +#define NCF_CONFIG_LOCK 0x80000000 +#define NCF_BLOCK_SIZE_MASK 0x70000000 +#define NCF_BLOCK_SIZE_SHIFT 28 +#define NCF_DEVICE_SIZE_MASK 0x0f000000 +#define NCF_DEVICE_SIZE_SHIFT 24 +#define NCF_DEVICE_WIDTH 0x00800000 +#define NCF_PAGE_SIZE_MASK 0x00300000 +#define NCF_PAGE_SIZE_SHIFT 20 +#define NCF_FULL_ADDR_BYTES_MASK 0x00070000 +#define NCF_FULL_ADDR_BYTES_SHIFT 16 +#define NCF_COL_ADDR_BYTES_MASK 0x00007000 +#define NCF_COL_ADDR_BYTES_SHIFT 12 +#define NCF_BLK_ADDR_BYTES_MASK 0x00000700 +#define NCF_BLK_ADDR_BYTES_SHIFT 8 + +/* nand_intfc_status */ +#define NIST_CTRL_READY 0x80000000 +#define NIST_FLASH_READY 0x40000000 +#define NIST_CACHE_VALID 0x20000000 +#define NIST_SPARE_VALID 0x10000000 +#define NIST_ERASED 0x08000000 +#define NIST_STATUS 0x000000ff + +#ifndef _LANGUAGE_ASSEMBLY +#include +#include +#include +#endif /* _LANGUAGE_ASSEMBLY */ + +#endif /* _nflash_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/qspi_core.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/qspi_core.h new file mode 100644 index 00000000000..832e8466987 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/include/qspi_core.h @@ -0,0 +1,1211 @@ +/* + * qspi - Broadcom QSPI specific definitions + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: qspi_core.h 596126 2015-10-29 19:53:48Z $ + */ + +#ifndef _qspi_core_h_ +#define _qspi_core_h_ + +/* cpp contortions to concatenate w/arg prescan */ +#ifndef PAD +#define _PADLINE(line) pad ## line +#define _XSTR(line) _PADLINE(line) +#define PAD _XSTR(__LINE__) +#endif /* PAD */ + +typedef volatile struct { + /* BSPI */ + uint32 bspi_revision_id; /* 0x0 */ + uint32 bspi_scratch; /* 0x4 */ + uint32 bspi_mast_n_boot_ctrl; /* 0x8 */ + uint32 bspi_busy_status; /* 0xc */ + uint32 bspi_intr_status; /* 0x10 */ + uint32 bspi_b0_status; /* 0x14 */ + uint32 bspi_b0_ctrl; /* 0x18 */ + uint32 bspi_b1_status; /* 0x1c */ + uint32 bspi_b1_ctrl; /* 0x20 */ + uint32 bspi_strap_override_ctrl; /* 0x24 */ + uint32 bspi_flex_mode_enable; /* 0x28 */ + uint32 bspi_bits_per_cycle; /* 0x2c */ + uint32 bspi_bits_per_phase; /* 0x30 */ + uint32 bspi_cmd_and_mode_byte; /* 0x34 */ + uint32 bspi_bspi_flash_upper_addr_byte; /* 0x38 */ + uint32 bspi_bspi_xor_value; /* 0x3c */ + uint32 bspi_bspi_xor_enable; /* 0x40 */ + uint32 bspi_bspi_pio_mode_enable; /* 0x44 */ + uint32 bspi_bspi_pio_iodir; /* 0x48 */ + uint32 bspi_bspi_pio_data; /* 0x4c */ + uint32 PAD[44]; /* 0x50 ~ 0xfc */ + + /* RAF */ + uint32 raf_start_addr; /* 0x100 */ + uint32 raf_num_words; /* 0x104 */ + uint32 raf_ctrl; /* 0x108 */ + uint32 raf_fullness; /* 0x10c */ + uint32 raf_watermark; /* 0x110 */ + uint32 raf_status; /* 0x114 */ + uint32 raf_read_data; /* 0x118 */ + uint32 raf_word_cnt; /* 0x11c */ + uint32 raf_curr_addr; /* 0x120 */ + uint32 PAD[55]; /* 0x124 ~ 0x1fc */ + + /* MSPI */ + uint32 mspi_spcr0_lsb; /* 0x200 */ + uint32 mspi_spcr0_msb; /* 0x204 */ + uint32 mspi_spcr1_lsb; /* 0x208 */ + uint32 mspi_spcr1_msb; /* 0x20c */ + uint32 mspi_newqp; /* 0x210 */ + uint32 mspi_endqp; /* 0x214 */ + uint32 mspi_spcr2; /* 0x218 */ + uint32 PAD; /* 0x21c */ + uint32 mspi_mspi_status; /* 0x220 */ + uint32 mspi_cptqp; /* 0x224 */ + uint32 PAD[6]; /* 0x228 ~ 0x23c */ + uint32 mspi_txram[32]; /* 0x240 ~ 0x2b8 */ + uint32 mspi_rxram[32]; /* 0x2c0 ~ 0x33c */ + uint32 mspi_cdram[16]; /* 0x340 ~ 0x37c */ + uint32 mspi_write_lock; /* 0x380 */ + uint32 mspi_disable_flush_gen; /* 0x384 */ + uint32 PAD[6]; /* 0x388 ~ 0x39C */ + + /* Interrupt */ + uint32 intr_raf_lr_fullness_reached; /* 0x3a0 */ + uint32 intr_raf_lr_truncated; /* 0x3a4 */ + uint32 intr_raf_lr_impatient; /* 0x3a8 */ + uint32 intr_raf_lr_session_done; /* 0x3ac */ + uint32 intr_raf_lr_overread; /* 0x3b0 */ + uint32 intr_mspi_done; /* 0x3b4 */ + uint32 intr_mspi_halt_set_transaction_done; /* 0x3b8 */ +} qspiregs_t; + +/* + * SPCR0_LSB - SPCR0_LSB REGISTER + */ +/* HIF_MSPI :: SPCR0_LSB :: reserved0 [31:08] */ +#define MSPI_SPCR0_LSB_reserved0_MASK 0xffffff00 +#define MSPI_SPCR0_LSB_reserved0_SHIFT 8 + +/* HIF_MSPI :: SPCR0_LSB :: SPBR [07:00] */ +#define MSPI_SPCR0_LSB_SPBR_MASK 0x000000ff +#define MSPI_SPCR0_LSB_SPBR_SHIFT 0 +#define MSPI_SPCR0_LSB_SPBR_DEFAULT 0 + +/* + * SPCR0_MSB - SPCR0_MSB Register + */ +/* HIF_MSPI :: SPCR0_MSB :: reserved0 [31:08] */ +#define MSPI_SPCR0_MSB_reserved0_MASK 0xffffff00 +#define MSPI_SPCR0_MSB_reserved0_SHIFT 8 + +/* HIF_MSPI :: SPCR0_MSB :: MSTR [07:07] */ +#define MSPI_SPCR0_MSB_MSTR_MASK 0x00000080 +#define MSPI_SPCR0_MSB_MSTR_SHIFT 7 +#define MSPI_SPCR0_MSB_MSTR_DEFAULT 1 + +/* HIF_MSPI :: SPCR0_MSB :: StartTransDelay [06:06] */ +#define MSPI_SPCR0_MSB_StartTransDelay_MASK 0x00000040 +#define MSPI_SPCR0_MSB_StartTransDelay_SHIFT 6 +#define MSPI_SPCR0_MSB_StartTransDelay_DEFAULT 0 + +/* HIF_MSPI :: SPCR0_MSB :: BitS [05:02] */ +#define MSPI_SPCR0_MSB_BitS_MASK 0x0000003c +#define MSPI_SPCR0_MSB_BitS_SHIFT 2 +#define MSPI_SPCR0_MSB_BitS_DEFAULT 0 + +/* HIF_MSPI :: SPCR0_MSB :: CPOL [01:01] */ +#define MSPI_SPCR0_MSB_CPOL_MASK 0x00000002 +#define MSPI_SPCR0_MSB_CPOL_SHIFT 1 +#define MSPI_SPCR0_MSB_CPOL_DEFAULT 0 + +/* HIF_MSPI :: SPCR0_MSB :: CPHA [00:00] */ +#define MSPI_SPCR0_MSB_CPHA_MASK 0x00000001 +#define MSPI_SPCR0_MSB_CPHA_SHIFT 0 +#define MSPI_SPCR0_MSB_CPHA_DEFAULT 0 + +/* + * SPCR1_LSB - SPCR1_LSB REGISTER + */ +/* HIF_MSPI :: SPCR1_LSB :: reserved0 [31:08] */ +#define MSPI_SPCR1_LSB_reserved0_MASK 0xffffff00 +#define MSPI_SPCR1_LSB_reserved0_SHIFT 8 + +/* HIF_MSPI :: SPCR1_LSB :: DTL [07:00] */ +#define MSPI_SPCR1_LSB_DTL_MASK 0x000000ff +#define MSPI_SPCR1_LSB_DTL_SHIFT 0 +#define MSPI_SPCR1_LSB_DTL_DEFAULT 0 + +/* + * SPCR1_MSB - SPCR1_MSB REGISTER + */ +/* HIF_MSPI :: SPCR1_MSB :: reserved0 [31:08] */ +#define MSPI_SPCR1_MSB_reserved0_MASK 0xffffff00 +#define MSPI_SPCR1_MSB_reserved0_SHIFT 8 + +/* HIF_MSPI :: SPCR1_MSB :: RDSCLK [07:00] */ +#define MSPI_SPCR1_MSB_RDSCLK_MASK 0x000000ff +#define MSPI_SPCR1_MSB_RDSCLK_SHIFT 0 +#define MSPI_SPCR1_MSB_RDSCLK_DEFAULT 0 + +/* + * NEWQP - NEWQP REGISTER + */ +/* HIF_MSPI :: NEWQP :: reserved0 [31:04] */ +#define MSPI_NEWQP_reserved0_MASK 0xfffffff0 +#define MSPI_NEWQP_reserved0_SHIFT 4 + +/* HIF_MSPI :: NEWQP :: newqp [03:00] */ +#define MSPI_NEWQP_newqp_MASK 0x0000000f +#define MSPI_NEWQP_newqp_SHIFT 0 +#define MSPI_NEWQP_newqp_DEFAULT 0 + +/* + * ENDQP - ENDQP REGISTER + */ +/* HIF_MSPI :: ENDQP :: reserved0 [31:04] */ +#define MSPI_ENDQP_reserved0_MASK 0xfffffff0 +#define MSPI_ENDQP_reserved0_SHIFT 4 + +/* HIF_MSPI :: ENDQP :: endqp [03:00] */ +#define MSPI_ENDQP_endqp_MASK 0x0000000f +#define MSPI_ENDQP_endqp_SHIFT 0 +#define MSPI_ENDQP_endqp_DEFAULT 0 + +/* + * SPCR2 - SPCR2 REGISTER + */ +/* HIF_MSPI :: SPCR2 :: reserved0 [31:08] */ +#define MSPI_SPCR2_reserved0_MASK 0xffffff00 +#define MSPI_SPCR2_reserved0_SHIFT 8 + +/* HIF_MSPI :: SPCR2 :: cont_after_cmd [07:07] */ +#define MSPI_SPCR2_cont_after_cmd_MASK 0x00000080 +#define MSPI_SPCR2_cont_after_cmd_SHIFT 7 +#define MSPI_SPCR2_cont_after_cmd_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: spe [06:06] */ +#define MSPI_SPCR2_spe_MASK 0x00000040 +#define MSPI_SPCR2_spe_SHIFT 6 +#define MSPI_SPCR2_spe_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: spifie [05:05] */ +#define MSPI_SPCR2_spifie_MASK 0x00000020 +#define MSPI_SPCR2_spifie_SHIFT 5 +#define MSPI_SPCR2_spifie_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: wren [04:04] */ +#define MSPI_SPCR2_wren_MASK 0x00000010 +#define MSPI_SPCR2_wren_SHIFT 4 +#define MSPI_SPCR2_wren_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: wrt0 [03:03] */ +#define MSPI_SPCR2_wrt0_MASK 0x00000008 +#define MSPI_SPCR2_wrt0_SHIFT 3 +#define MSPI_SPCR2_wrt0_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: loopq [02:02] */ +#define MSPI_SPCR2_loopq_MASK 0x00000004 +#define MSPI_SPCR2_loopq_SHIFT 2 +#define MSPI_SPCR2_loopq_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: hie [01:01] */ +#define MSPI_SPCR2_hie_MASK 0x00000002 +#define MSPI_SPCR2_hie_SHIFT 1 +#define MSPI_SPCR2_hie_DEFAULT 0 + +/* HIF_MSPI :: SPCR2 :: halt [00:00] */ +#define MSPI_SPCR2_halt_MASK 0x00000001 +#define MSPI_SPCR2_halt_SHIFT 0 +#define MSPI_SPCR2_halt_DEFAULT 0 + +/* + * MSPI_STATUS - MSPI STATUS REGISTER + */ +/* HIF_MSPI :: MSPI_STATUS :: reserved0 [31:02] */ +#define MSPI_MSPI_STATUS_reserved0_MASK 0xfffffffc +#define MSPI_MSPI_STATUS_reserved0_SHIFT 2 + +/* HIF_MSPI :: MSPI_STATUS :: HALTA [01:01] */ +#define MSPI_MSPI_STATUS_HALTA_MASK 0x00000002 +#define MSPI_MSPI_STATUS_HALTA_SHIFT 1 +#define MSPI_MSPI_STATUS_HALTA_DEFAULT 0 + +/* HIF_MSPI :: MSPI_STATUS :: SPIF [00:00] */ +#define MSPI_MSPI_STATUS_SPIF_MASK 0x00000001 +#define MSPI_MSPI_STATUS_SPIF_SHIFT 0 +#define MSPI_MSPI_STATUS_SPIF_DEFAULT 0 + +/* + * CPTQP - CPTQP REGISTER + */ +/* HIF_MSPI :: CPTQP :: reserved0 [31:04] */ +#define MSPI_CPTQP_reserved0_MASK 0xfffffff0 +#define MSPI_CPTQP_reserved0_SHIFT 4 + +/* HIF_MSPI :: CPTQP :: cptqp [03:00] */ +#define MSPI_CPTQP_cptqp_MASK 0x0000000f +#define MSPI_CPTQP_cptqp_SHIFT 0 +#define MSPI_CPTQP_cptqp_DEFAULT 0 + +/* + * TXRAM00 - MSbyte for bit 16 or bit 8 operation (queue pointer = 0) + */ +/* HIF_MSPI :: TXRAM00 :: reserved0 [31:08] */ +#define MSPI_TXRAM00_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM00_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM00 :: txram [07:00] */ +#define MSPI_TXRAM00_txram_MASK 0x000000ff +#define MSPI_TXRAM00_txram_SHIFT 0 + +/* + * TXRAM01 - LSbyte for bit 16 operation only (queue pointer = 0) + */ +/* HIF_MSPI :: TXRAM01 :: reserved0 [31:08] */ +#define MSPI_TXRAM01_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM01_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM01 :: txram [07:00] */ +#define MSPI_TXRAM01_txram_MASK 0x000000ff +#define MSPI_TXRAM01_txram_SHIFT 0 + +/* + * TXRAM02 - MSbyte for bit 16 or bit 8 operation (queue pointer = 1) + */ +/* HIF_MSPI :: TXRAM02 :: reserved0 [31:08] */ +#define MSPI_TXRAM02_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM02_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM02 :: txram [07:00] */ +#define MSPI_TXRAM02_txram_MASK 0x000000ff +#define MSPI_TXRAM02_txram_SHIFT 0 + +/* + * TXRAM03 - LSbyte for bit 16 operation only (queue pointer = 1) + */ +/* HIF_MSPI :: TXRAM03 :: reserved0 [31:08] */ +#define MSPI_TXRAM03_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM03_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM03 :: txram [07:00] */ +#define MSPI_TXRAM03_txram_MASK 0x000000ff +#define MSPI_TXRAM03_txram_SHIFT 0 + +/* + * TXRAM04 - MSbyte for bit 16 or bit 8 operation (queue pointer = 2) + */ +/* HIF_MSPI :: TXRAM04 :: reserved0 [31:08] */ +#define MSPI_TXRAM04_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM04_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM04 :: txram [07:00] */ +#define MSPI_TXRAM04_txram_MASK 0x000000ff +#define MSPI_TXRAM04_txram_SHIFT 0 + +/* + * TXRAM05 - LSbyte for bit 16 operation only (queue pointer = 2) + */ +/* HIF_MSPI :: TXRAM05 :: reserved0 [31:08] */ +#define MSPI_TXRAM05_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM05_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM05 :: txram [07:00] */ +#define MSPI_TXRAM05_txram_MASK 0x000000ff +#define MSPI_TXRAM05_txram_SHIFT 0 + +/* + * TXRAM06 - MSbyte for bit 16 or bit 8 operation (queue pointer = 3) + */ +/* HIF_MSPI :: TXRAM06 :: reserved0 [31:08] */ +#define MSPI_TXRAM06_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM06_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM06 :: txram [07:00] */ +#define MSPI_TXRAM06_txram_MASK 0x000000ff +#define MSPI_TXRAM06_txram_SHIFT 0 + +/* + * TXRAM07 - LSbyte for bit 16 operation only (queue pointer = 3) + */ +/* HIF_MSPI :: TXRAM07 :: reserved0 [31:08] */ +#define MSPI_TXRAM07_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM07_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM07 :: txram [07:00] */ +#define MSPI_TXRAM07_txram_MASK 0x000000ff +#define MSPI_TXRAM07_txram_SHIFT 0 + +/* + * TXRAM08 - MSbyte for bit 16 or bit 8 operation (queue pointer = 4) + */ +/* HIF_MSPI :: TXRAM08 :: reserved0 [31:08] */ +#define MSPI_TXRAM08_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM08_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM08 :: txram [07:00] */ +#define MSPI_TXRAM08_txram_MASK 0x000000ff +#define MSPI_TXRAM08_txram_SHIFT 0 + +/* + * TXRAM09 - LSbyte for bit 16 operation only (queue pointer = 4) + */ +/* HIF_MSPI :: TXRAM09 :: reserved0 [31:08] */ +#define MSPI_TXRAM09_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM09_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM09 :: txram [07:00] */ +#define MSPI_TXRAM09_txram_MASK 0x000000ff +#define MSPI_TXRAM09_txram_SHIFT 0 + +/* + * TXRAM10 - MSbyte for bit 16 or bit 8 operation (queue pointer = 5) + */ +/* HIF_MSPI :: TXRAM10 :: reserved0 [31:08] */ +#define MSPI_TXRAM10_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM10_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM10 :: txram [07:00] */ +#define MSPI_TXRAM10_txram_MASK 0x000000ff +#define MSPI_TXRAM10_txram_SHIFT 0 + +/* + * TXRAM11 - LSbyte for bit 16 operation only (queue pointer = 5) + */ +/* HIF_MSPI :: TXRAM11 :: reserved0 [31:08] */ +#define MSPI_TXRAM11_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM11_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM11 :: txram [07:00] */ +#define MSPI_TXRAM11_txram_MASK 0x000000ff +#define MSPI_TXRAM11_txram_SHIFT 0 + +/* + * TXRAM12 - MSbyte for bit 16 or bit 8 operation (queue pointer = 6) + */ +/* HIF_MSPI :: TXRAM12 :: reserved0 [31:08] */ +#define MSPI_TXRAM12_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM12_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM12 :: txram [07:00] */ +#define MSPI_TXRAM12_txram_MASK 0x000000ff +#define MSPI_TXRAM12_txram_SHIFT 0 + +/* + * TXRAM13 - LSbyte for bit 16 operation only (queue pointer = 6) + */ +/* HIF_MSPI :: TXRAM13 :: reserved0 [31:08] */ +#define MSPI_TXRAM13_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM13_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM13 :: txram [07:00] */ +#define MSPI_TXRAM13_txram_MASK 0x000000ff +#define MSPI_TXRAM13_txram_SHIFT 0 + +/* + * TXRAM14 - MSbyte for bit 16 or bit 8 operation (queue pointer = 7) + */ +/* HIF_MSPI :: TXRAM14 :: reserved0 [31:08] */ +#define MSPI_TXRAM14_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM14_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM14 :: txram [07:00] */ +#define MSPI_TXRAM14_txram_MASK 0x000000ff +#define MSPI_TXRAM14_txram_SHIFT 0 + +/* + * TXRAM15 - LSbyte for bit 16 operation only (queue pointer = 7) + */ +/* HIF_MSPI :: TXRAM15 :: reserved0 [31:08] */ +#define MSPI_TXRAM15_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM15_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM15 :: txram [07:00] */ +#define MSPI_TXRAM15_txram_MASK 0x000000ff +#define MSPI_TXRAM15_txram_SHIFT 0 + +/* + * TXRAM16 - MSbyte for bit 16 or bit 8 operation (queue pointer = 8) + */ +/* HIF_MSPI :: TXRAM16 :: reserved0 [31:08] */ +#define MSPI_TXRAM16_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM16_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM16 :: txram [07:00] */ +#define MSPI_TXRAM16_txram_MASK 0x000000ff +#define MSPI_TXRAM16_txram_SHIFT 0 + +/* + * TXRAM17 - LSbyte for bit 16 operation only (queue pointer = 8) + */ +/* HIF_MSPI :: TXRAM17 :: reserved0 [31:08] */ +#define MSPI_TXRAM17_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM17_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM17 :: txram [07:00] */ +#define MSPI_TXRAM17_txram_MASK 0x000000ff +#define MSPI_TXRAM17_txram_SHIFT 0 + +/* + * TXRAM18 - MSbyte for bit 16 or bit 8 operation (queue pointer = 9) + */ +/* HIF_MSPI :: TXRAM18 :: reserved0 [31:08] */ +#define MSPI_TXRAM18_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM18_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM18 :: txram [07:00] */ +#define MSPI_TXRAM18_txram_MASK 0x000000ff +#define MSPI_TXRAM18_txram_SHIFT 0 + +/* + * TXRAM19 - LSbyte for bit 16 operation only (queue pointer = 9) + */ +/* HIF_MSPI :: TXRAM19 :: reserved0 [31:08] */ +#define MSPI_TXRAM19_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM19_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM19 :: txram [07:00] */ +#define MSPI_TXRAM19_txram_MASK 0x000000ff +#define MSPI_TXRAM19_txram_SHIFT 0 + +/* + * TXRAM20 - MSbyte for bit 16 or bit 8 operation (queue pointer = a) + */ +/* HIF_MSPI :: TXRAM20 :: reserved0 [31:08] */ +#define MSPI_TXRAM20_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM20_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM20 :: txram [07:00] */ +#define MSPI_TXRAM20_txram_MASK 0x000000ff +#define MSPI_TXRAM20_txram_SHIFT 0 + +/* + * TXRAM21 - LSbyte for bit 16 operation only (queue pointer = a) + */ +/* HIF_MSPI :: TXRAM21 :: reserved0 [31:08] */ +#define MSPI_TXRAM21_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM21_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM21 :: txram [07:00] */ +#define MSPI_TXRAM21_txram_MASK 0x000000ff +#define MSPI_TXRAM21_txram_SHIFT 0 + +/* + * TXRAM22 - MSbyte for bit 16 or bit 8 operation (queue pointer = b) + */ +/* HIF_MSPI :: TXRAM22 :: reserved0 [31:08] */ +#define MSPI_TXRAM22_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM22_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM22 :: txram [07:00] */ +#define MSPI_TXRAM22_txram_MASK 0x000000ff +#define MSPI_TXRAM22_txram_SHIFT 0 + +/* + * TXRAM23 - LSbyte for bit 16 operation only (queue pointer = b) + */ +/* HIF_MSPI :: TXRAM23 :: reserved0 [31:08] */ +#define MSPI_TXRAM23_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM23_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM23 :: txram [07:00] */ +#define MSPI_TXRAM23_txram_MASK 0x000000ff +#define MSPI_TXRAM23_txram_SHIFT 0 + +/* + * TXRAM24 - MSbyte for bit 16 or bit 8 operation (queue pointer = c) + */ +/* HIF_MSPI :: TXRAM24 :: reserved0 [31:08] */ +#define MSPI_TXRAM24_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM24_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM24 :: txram [07:00] */ +#define MSPI_TXRAM24_txram_MASK 0x000000ff +#define MSPI_TXRAM24_txram_SHIFT 0 + +/* + * TXRAM25 - LSbyte for bit 16 operation only (queue pointer = c) + */ +/* HIF_MSPI :: TXRAM25 :: reserved0 [31:08] */ +#define MSPI_TXRAM25_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM25_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM25 :: txram [07:00] */ +#define MSPI_TXRAM25_txram_MASK 0x000000ff +#define MSPI_TXRAM25_txram_SHIFT 0 + +/* + * TXRAM26 - MSbyte for bit 16 or bit 8 operation (queue pointer = d) + */ +/* HIF_MSPI :: TXRAM26 :: reserved0 [31:08] */ +#define MSPI_TXRAM26_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM26_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM26 :: txram [07:00] */ +#define MSPI_TXRAM26_txram_MASK 0x000000ff +#define MSPI_TXRAM26_txram_SHIFT 0 + +/* + * TXRAM27 - LSbyte for bit 16 operation only (queue pointer = d) + */ +/* HIF_MSPI :: TXRAM27 :: reserved0 [31:08] */ +#define MSPI_TXRAM27_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM27_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM27 :: txram [07:00] */ +#define MSPI_TXRAM27_txram_MASK 0x000000ff +#define MSPI_TXRAM27_txram_SHIFT 0 + +/* + * TXRAM28 - MSbyte for bit 16 or bit 8 operation (queue pointer = e) + */ +/* HIF_MSPI :: TXRAM28 :: reserved0 [31:08] */ +#define MSPI_TXRAM28_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM28_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM28 :: txram [07:00] */ +#define MSPI_TXRAM28_txram_MASK 0x000000ff +#define MSPI_TXRAM28_txram_SHIFT 0 + +/* + * TXRAM29 - LSbyte for bit 16 operation only (queue pointer = e) + */ +/* HIF_MSPI :: TXRAM29 :: reserved0 [31:08] */ +#define MSPI_TXRAM29_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM29_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM29 :: txram [07:00] */ +#define MSPI_TXRAM29_txram_MASK 0x000000ff +#define MSPI_TXRAM29_txram_SHIFT 0 + +/* + * TXRAM30 - MSbyte for bit 16 or bit 8 operation (queue pointer = f) + */ +/* HIF_MSPI :: TXRAM30 :: reserved0 [31:08] */ +#define MSPI_TXRAM30_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM30_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM30 :: txram [07:00] */ +#define MSPI_TXRAM30_txram_MASK 0x000000ff +#define MSPI_TXRAM30_txram_SHIFT 0 + +/* + * TXRAM31 - LSbyte for bit 16 operation only (queue pointer = f) + */ +/* HIF_MSPI :: TXRAM31 :: reserved0 [31:08] */ +#define MSPI_TXRAM31_reserved0_MASK 0xffffff00 +#define MSPI_TXRAM31_reserved0_SHIFT 8 + +/* HIF_MSPI :: TXRAM31 :: txram [07:00] */ +#define MSPI_TXRAM31_txram_MASK 0x000000ff +#define MSPI_TXRAM31_txram_SHIFT 0 + +/* + * RXRAM00 - MSbyte for bit 16 or bit 8 operation (queue pointer = 0) + */ +/* HIF_MSPI :: RXRAM00 :: reserved0 [31:08] */ +#define MSPI_RXRAM00_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM00_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM00 :: rxram [07:00] */ +#define MSPI_RXRAM00_rxram_MASK 0x000000ff +#define MSPI_RXRAM00_rxram_SHIFT 0 + +/* + * RXRAM01 - LSbyte for bit 16 operation only (queue pointer = 0) + */ +/* HIF_MSPI :: RXRAM01 :: reserved0 [31:08] */ +#define MSPI_RXRAM01_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM01_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM01 :: rxram [07:00] */ +#define MSPI_RXRAM01_rxram_MASK 0x000000ff +#define MSPI_RXRAM01_rxram_SHIFT 0 + +/* + * RXRAM02 - MSbyte for bit 16 or bit 8 operation (queue pointer = 1) + */ +/* HIF_MSPI :: RXRAM02 :: reserved0 [31:08] */ +#define MSPI_RXRAM02_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM02_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM02 :: rxram [07:00] */ +#define MSPI_RXRAM02_rxram_MASK 0x000000ff +#define MSPI_RXRAM02_rxram_SHIFT 0 + +/* + * RXRAM03 - LSbyte for bit 16 operation only (queue pointer = 1) + */ +/* HIF_MSPI :: RXRAM03 :: reserved0 [31:08] */ +#define MSPI_RXRAM03_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM03_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM03 :: rxram [07:00] */ +#define MSPI_RXRAM03_rxram_MASK 0x000000ff +#define MSPI_RXRAM03_rxram_SHIFT 0 + +/* + * RXRAM04 - MSbyte for bit 16 or bit 8 operation (queue pointer = 2) + */ +/* HIF_MSPI :: RXRAM04 :: reserved0 [31:08] */ +#define MSPI_RXRAM04_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM04_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM04 :: rxram [07:00] */ +#define MSPI_RXRAM04_rxram_MASK 0x000000ff +#define MSPI_RXRAM04_rxram_SHIFT 0 + +/* + * RXRAM05 - LSbyte for bit 16 operation only (queue pointer = 2) + */ +/* HIF_MSPI :: RXRAM05 :: reserved0 [31:08] */ +#define MSPI_RXRAM05_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM05_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM05 :: rxram [07:00] */ +#define MSPI_RXRAM05_rxram_MASK 0x000000ff +#define MSPI_RXRAM05_rxram_SHIFT 0 + +/* + * RXRAM06 - MSbyte for bit 16 or bit 8 operation (queue pointer = 3) + */ +/* HIF_MSPI :: RXRAM06 :: reserved0 [31:08] */ +#define MSPI_RXRAM06_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM06_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM06 :: rxram [07:00] */ +#define MSPI_RXRAM06_rxram_MASK 0x000000ff +#define MSPI_RXRAM06_rxram_SHIFT 0 + +/* + * RXRAM07 - LSbyte for bit 16 operation only (queue pointer = 3) + */ +/* HIF_MSPI :: RXRAM07 :: reserved0 [31:08] */ +#define MSPI_RXRAM07_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM07_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM07 :: rxram [07:00] */ +#define MSPI_RXRAM07_rxram_MASK 0x000000ff +#define MSPI_RXRAM07_rxram_SHIFT 0 + +/* + * RXRAM08 - MSbyte for bit 16 or bit 8 operation (queue pointer = 4) + */ +/* HIF_MSPI :: RXRAM08 :: reserved0 [31:08] */ +#define MSPI_RXRAM08_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM08_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM08 :: rxram [07:00] */ +#define MSPI_RXRAM08_rxram_MASK 0x000000ff +#define MSPI_RXRAM08_rxram_SHIFT 0 + +/* + * RXRAM09 - LSbyte for bit 16 operation only (queue pointer = 4) + */ +/* HIF_MSPI :: RXRAM09 :: reserved0 [31:08] */ +#define MSPI_RXRAM09_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM09_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM09 :: rxram [07:00] */ +#define MSPI_RXRAM09_rxram_MASK 0x000000ff +#define MSPI_RXRAM09_rxram_SHIFT 0 + +/* + * RXRAM10 - MSbyte for bit 16 or bit 8 operation (queue pointer = 5) + */ +/* HIF_MSPI :: RXRAM10 :: reserved0 [31:08] */ +#define MSPI_RXRAM10_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM10_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM10 :: rxram [07:00] */ +#define MSPI_RXRAM10_rxram_MASK 0x000000ff +#define MSPI_RXRAM10_rxram_SHIFT 0 + +/* + * RXRAM11 - LSbyte for bit 16 operation only (queue pointer = 5) + */ +/* HIF_MSPI :: RXRAM11 :: reserved0 [31:08] */ +#define MSPI_RXRAM11_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM11_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM11 :: rxram [07:00] */ +#define MSPI_RXRAM11_rxram_MASK 0x000000ff +#define MSPI_RXRAM11_rxram_SHIFT 0 + +/* + * RXRAM12 - MSbyte for bit 16 or bit 8 operation (queue pointer = 6) + */ +/* HIF_MSPI :: RXRAM12 :: reserved0 [31:08] */ +#define MSPI_RXRAM12_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM12_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM12 :: rxram [07:00] */ +#define MSPI_RXRAM12_rxram_MASK 0x000000ff +#define MSPI_RXRAM12_rxram_SHIFT 0 + +/* + * RXRAM13 - LSbyte for bit 16 operation only (queue pointer = 6) + */ +/* HIF_MSPI :: RXRAM13 :: reserved0 [31:08] */ +#define MSPI_RXRAM13_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM13_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM13 :: rxram [07:00] */ +#define MSPI_RXRAM13_rxram_MASK 0x000000ff +#define MSPI_RXRAM13_rxram_SHIFT 0 + +/* + * RXRAM14 - MSbyte for bit 16 or bit 8 operation (queue pointer = 7) + */ +/* HIF_MSPI :: RXRAM14 :: reserved0 [31:08] */ +#define MSPI_RXRAM14_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM14_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM14 :: rxram [07:00] */ +#define MSPI_RXRAM14_rxram_MASK 0x000000ff +#define MSPI_RXRAM14_rxram_SHIFT 0 + +/* + * RXRAM15 - LSbyte for bit 16 operation only (queue pointer = 7) + */ +/* HIF_MSPI :: RXRAM15 :: reserved0 [31:08] */ +#define MSPI_RXRAM15_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM15_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM15 :: rxram [07:00] */ +#define MSPI_RXRAM15_rxram_MASK 0x000000ff +#define MSPI_RXRAM15_rxram_SHIFT 0 + +/* + * RXRAM16 - MSbyte for bit 16 or bit 8 operation (queue pointer = 8) + */ +/* HIF_MSPI :: RXRAM16 :: reserved0 [31:08] */ +#define MSPI_RXRAM16_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM16_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM16 :: rxram [07:00] */ +#define MSPI_RXRAM16_rxram_MASK 0x000000ff +#define MSPI_RXRAM16_rxram_SHIFT 0 + +/* + * RXRAM17 - LSbyte for bit 16 operation only (queue pointer = 8) + */ +/* HIF_MSPI :: RXRAM17 :: reserved0 [31:08] */ +#define MSPI_RXRAM17_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM17_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM17 :: rxram [07:00] */ +#define MSPI_RXRAM17_rxram_MASK 0x000000ff +#define MSPI_RXRAM17_rxram_SHIFT 0 + +/* + * RXRAM18 - MSbyte for bit 16 or bit 8 operation (queue pointer = 9) + */ +/* HIF_MSPI :: RXRAM18 :: reserved0 [31:08] */ +#define MSPI_RXRAM18_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM18_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM18 :: rxram [07:00] */ +#define MSPI_RXRAM18_rxram_MASK 0x000000ff +#define MSPI_RXRAM18_rxram_SHIFT 0 + +/* + * RXRAM19 - LSbyte for bit 16 operation only (queue pointer = 9) + */ +/* HIF_MSPI :: RXRAM19 :: reserved0 [31:08] */ +#define MSPI_RXRAM19_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM19_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM19 :: rxram [07:00] */ +#define MSPI_RXRAM19_rxram_MASK 0x000000ff +#define MSPI_RXRAM19_rxram_SHIFT 0 + +/* + * RXRAM20 - MSbyte for bit 16 or bit 8 operation (queue pointer = a) + */ +/* HIF_MSPI :: RXRAM20 :: reserved0 [31:08] */ +#define MSPI_RXRAM20_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM20_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM20 :: rxram [07:00] */ +#define MSPI_RXRAM20_rxram_MASK 0x000000ff +#define MSPI_RXRAM20_rxram_SHIFT 0 + +/* + * RXRAM21 - LSbyte for bit 16 operation only (queue pointer = a) + */ +/* HIF_MSPI :: RXRAM21 :: reserved0 [31:08] */ +#define MSPI_RXRAM21_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM21_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM21 :: rxram [07:00] */ +#define MSPI_RXRAM21_rxram_MASK 0x000000ff +#define MSPI_RXRAM21_rxram_SHIFT 0 + +/* + * RXRAM22 - MSbyte for bit 16 or bit 8 operation (queue pointer = b) + */ +/* HIF_MSPI :: RXRAM22 :: reserved0 [31:08] */ +#define MSPI_RXRAM22_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM22_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM22 :: rxram [07:00] */ +#define MSPI_RXRAM22_rxram_MASK 0x000000ff +#define MSPI_RXRAM22_rxram_SHIFT 0 + +/* + * RXRAM23 - LSbyte for bit 16 operation only (queue pointer = b) + */ +/* HIF_MSPI :: RXRAM23 :: reserved0 [31:08] */ +#define MSPI_RXRAM23_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM23_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM23 :: rxram [07:00] */ +#define MSPI_RXRAM23_rxram_MASK 0x000000ff +#define MSPI_RXRAM23_rxram_SHIFT 0 + +/* + * RXRAM24 - MSbyte for bit 16 or bit 8 operation (queue pointer = c) + */ +/* HIF_MSPI :: RXRAM24 :: reserved0 [31:08] */ +#define MSPI_RXRAM24_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM24_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM24 :: rxram [07:00] */ +#define MSPI_RXRAM24_rxram_MASK 0x000000ff +#define MSPI_RXRAM24_rxram_SHIFT 0 + +/* + * RXRAM25 - LSbyte for bit 16 operation only (queue pointer = c) + */ +/* HIF_MSPI :: RXRAM25 :: reserved0 [31:08] */ +#define MSPI_RXRAM25_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM25_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM25 :: rxram [07:00] */ +#define MSPI_RXRAM25_rxram_MASK 0x000000ff +#define MSPI_RXRAM25_rxram_SHIFT 0 + +/* + * RXRAM26 - MSbyte for bit 16 or bit 8 operation (queue pointer = d) + */ +/* HIF_MSPI :: RXRAM26 :: reserved0 [31:08] */ +#define MSPI_RXRAM26_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM26_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM26 :: rxram [07:00] */ +#define MSPI_RXRAM26_rxram_MASK 0x000000ff +#define MSPI_RXRAM26_rxram_SHIFT 0 + +/* + * RXRAM27 - LSbyte for bit 16 operation only (queue pointer = d) + */ +/* HIF_MSPI :: RXRAM27 :: reserved0 [31:08] */ +#define MSPI_RXRAM27_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM27_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM27 :: rxram [07:00] */ +#define MSPI_RXRAM27_rxram_MASK 0x000000ff +#define MSPI_RXRAM27_rxram_SHIFT 0 + +/* + * RXRAM28 - MSbyte for bit 16 or bit 8 operation (queue pointer = e) + */ +/* HIF_MSPI :: RXRAM28 :: reserved0 [31:08] */ +#define MSPI_RXRAM28_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM28_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM28 :: rxram [07:00] */ +#define MSPI_RXRAM28_rxram_MASK 0x000000ff +#define MSPI_RXRAM28_rxram_SHIFT 0 + +/* + * RXRAM29 - LSbyte for bit 16 operation only (queue pointer = e) + */ +/* HIF_MSPI :: RXRAM29 :: reserved0 [31:08] */ +#define MSPI_RXRAM29_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM29_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM29 :: rxram [07:00] */ +#define MSPI_RXRAM29_rxram_MASK 0x000000ff +#define MSPI_RXRAM29_rxram_SHIFT 0 + +/* + * RXRAM30 - MSbyte for bit 16 or bit 8 operation (queue pointer = f) + */ +/* HIF_MSPI :: RXRAM30 :: reserved0 [31:08] */ +#define MSPI_RXRAM30_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM30_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM30 :: rxram [07:00] */ +#define MSPI_RXRAM30_rxram_MASK 0x000000ff +#define MSPI_RXRAM30_rxram_SHIFT 0 + +/* + * RXRAM31 - LSbyte for bit 16 operation only (queue pointer = f) + */ +/* HIF_MSPI :: RXRAM31 :: reserved0 [31:08] */ +#define MSPI_RXRAM31_reserved0_MASK 0xffffff00 +#define MSPI_RXRAM31_reserved0_SHIFT 8 + +/* HIF_MSPI :: RXRAM31 :: rxram [07:00] */ +#define MSPI_RXRAM31_rxram_MASK 0x000000ff +#define MSPI_RXRAM31_rxram_SHIFT 0 + +/* + * CDRAM00 - 8-bit command (queue pointer = 0) + */ +/* HIF_MSPI :: CDRAM00 :: reserved0 [31:08] */ +#define MSPI_CDRAM00_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM00_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM00 :: cdram [07:00] */ +#define MSPI_CDRAM00_cdram_MASK 0x000000ff +#define MSPI_CDRAM00_cdram_SHIFT 0 + +/* + * CDRAM01 - 8-bit command (queue pointer = 1) + */ +/* HIF_MSPI :: CDRAM01 :: reserved0 [31:08] */ +#define MSPI_CDRAM01_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM01_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM01 :: cdram [07:00] */ +#define MSPI_CDRAM01_cdram_MASK 0x000000ff +#define MSPI_CDRAM01_cdram_SHIFT 0 + +/* + * CDRAM02 - 8-bit command (queue pointer = 2) + */ +/* HIF_MSPI :: CDRAM02 :: reserved0 [31:08] */ +#define MSPI_CDRAM02_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM02_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM02 :: cdram [07:00] */ +#define MSPI_CDRAM02_cdram_MASK 0x000000ff +#define MSPI_CDRAM02_cdram_SHIFT 0 + +/* + * CDRAM03 - 8-bit command (queue pointer = 3) + */ +/* HIF_MSPI :: CDRAM03 :: reserved0 [31:08] */ +#define MSPI_CDRAM03_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM03_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM03 :: cdram [07:00] */ +#define MSPI_CDRAM03_cdram_MASK 0x000000ff +#define MSPI_CDRAM03_cdram_SHIFT 0 + +/* + * CDRAM04 - 8-bit command (queue pointer = 4) + */ +/* HIF_MSPI :: CDRAM04 :: reserved0 [31:08] */ +#define MSPI_CDRAM04_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM04_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM04 :: cdram [07:00] */ +#define MSPI_CDRAM04_cdram_MASK 0x000000ff +#define MSPI_CDRAM04_cdram_SHIFT 0 + +/* + * CDRAM05 - 8-bit command (queue pointer = 5) + */ +/* HIF_MSPI :: CDRAM05 :: reserved0 [31:08] */ +#define MSPI_CDRAM05_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM05_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM05 :: cdram [07:00] */ +#define MSPI_CDRAM05_cdram_MASK 0x000000ff +#define MSPI_CDRAM05_cdram_SHIFT 0 + +/* + * CDRAM06 - 8-bit command (queue pointer = 6) + */ +/* HIF_MSPI :: CDRAM06 :: reserved0 [31:08] */ +#define MSPI_CDRAM06_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM06_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM06 :: cdram [07:00] */ +#define MSPI_CDRAM06_cdram_MASK 0x000000ff +#define MSPI_CDRAM06_cdram_SHIFT 0 + +/* + * CDRAM07 - 8-bit command (queue pointer = 7) + */ +/* HIF_MSPI :: CDRAM07 :: reserved0 [31:08] */ +#define MSPI_CDRAM07_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM07_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM07 :: cdram [07:00] */ +#define MSPI_CDRAM07_cdram_MASK 0x000000ff +#define MSPI_CDRAM07_cdram_SHIFT 0 + +/* + * CDRAM08 - 8-bit command (queue pointer = 8) + */ +/* HIF_MSPI :: CDRAM08 :: reserved0 [31:08] */ +#define MSPI_CDRAM08_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM08_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM08 :: cdram [07:00] */ +#define MSPI_CDRAM08_cdram_MASK 0x000000ff +#define MSPI_CDRAM08_cdram_SHIFT 0 + +/* + * CDRAM09 - 8-bit command (queue pointer = 9) + */ +/* HIF_MSPI :: CDRAM09 :: reserved0 [31:08] */ +#define MSPI_CDRAM09_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM09_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM09 :: cdram [07:00] */ +#define MSPI_CDRAM09_cdram_MASK 0x000000ff +#define MSPI_CDRAM09_cdram_SHIFT 0 + +/* + * CDRAM10 - 8-bit command (queue pointer = a) + */ +/* HIF_MSPI :: CDRAM10 :: reserved0 [31:08] */ +#define MSPI_CDRAM10_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM10_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM10 :: cdram [07:00] */ +#define MSPI_CDRAM10_cdram_MASK 0x000000ff +#define MSPI_CDRAM10_cdram_SHIFT 0 + +/* + * CDRAM11 - 8-bit command (queue pointer = b) + */ +/* HIF_MSPI :: CDRAM11 :: reserved0 [31:08] */ +#define MSPI_CDRAM11_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM11_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM11 :: cdram [07:00] */ +#define MSPI_CDRAM11_cdram_MASK 0x000000ff +#define MSPI_CDRAM11_cdram_SHIFT 0 + +/* + * CDRAM12 - 8-bit command (queue pointer = c) + */ +/* HIF_MSPI :: CDRAM12 :: reserved0 [31:08] */ +#define MSPI_CDRAM12_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM12_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM12 :: cdram [07:00] */ +#define MSPI_CDRAM12_cdram_MASK 0x000000ff +#define MSPI_CDRAM12_cdram_SHIFT 0 + +/* + * CDRAM13 - 8-bit command (queue pointer = d) + */ +/* HIF_MSPI :: CDRAM13 :: reserved0 [31:08] */ +#define MSPI_CDRAM13_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM13_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM13 :: cdram [07:00] */ +#define MSPI_CDRAM13_cdram_MASK 0x000000ff +#define MSPI_CDRAM13_cdram_SHIFT 0 + +/* + * CDRAM14 - 8-bit command (queue pointer = e) + */ +/* HIF_MSPI :: CDRAM14 :: reserved0 [31:08] */ +#define MSPI_CDRAM14_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM14_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM14 :: cdram [07:00] */ +#define MSPI_CDRAM14_cdram_MASK 0x000000ff +#define MSPI_CDRAM14_cdram_SHIFT 0 + +/* + * CDRAM15 - 8-bit command (queue pointer = f) + */ +/* HIF_MSPI :: CDRAM15 :: reserved0 [31:08] */ +#define MSPI_CDRAM15_reserved0_MASK 0xffffff00 +#define MSPI_CDRAM15_reserved0_SHIFT 8 + +/* HIF_MSPI :: CDRAM15 :: cdram [07:00] */ +#define MSPI_CDRAM15_cdram_MASK 0x000000ff +#define MSPI_CDRAM15_cdram_SHIFT 0 + +/* + * WRITE_LOCK - Control bit to lock group of write commands + */ +/* HIF_MSPI :: WRITE_LOCK :: reserved0 [31:01] */ +#define MSPI_WRITE_LOCK_reserved0_MASK 0xfffffffe +#define MSPI_WRITE_LOCK_reserved0_SHIFT 1 + +/* HIF_MSPI :: WRITE_LOCK :: WriteLock [00:00] */ +#define MSPI_WRITE_LOCK_WriteLock_MASK 0x00000001 +#define MSPI_WRITE_LOCK_WriteLock_SHIFT 0 +#define MSPI_WRITE_LOCK_WriteLock_DEFAULT 0 + +/* + * DISABLE_FLUSH_GEN - Debug bit to mask the generation of flush signals from Mspi + */ +/* HIF_MSPI :: DISABLE_FLUSH_GEN :: reserved0 [31:01] */ +#define MSPI_DISABLE_FLUSH_GEN_reserved0_MASK 0xfffffffe +#define MSPI_DISABLE_FLUSH_GEN_reserved0_SHIFT 1 + +/* HIF_MSPI :: DISABLE_FLUSH_GEN :: DisableFlushGen [00:00] */ +#define MSPI_DISABLE_FLUSH_GEN_DisableFlushGen_MASK 0x00000001 +#define MSPI_DISABLE_FLUSH_GEN_DisableFlushGen_SHIFT 0 +#define MSPI_DISABLE_FLUSH_GEN_DisableFlushGen_DEFAULT 0 + +/* BSPI register fields */ +#define BSPI_BITS_PER_PHASE_ADDR_MARK 0x00010000 + +#define SPI_PP_CMD (0x02) +#define SPI_READ_CMD (0x03) +#define SPI_WRDI_CMD (0x04) +#define SPI_RDSR_CMD (0x05) +#define SPI_WREN_CMD (0x06) +#define SPI_SSE_CMD (0x20) +#define SPI_READ_ID_CMD (0x90) +#define SPI_RDID_CMD (0x9F) +#define SPI_SE_CMD (0xD8) +#define SPI_EN4B_CMD (0xB7) +#define SPI_EX4B_CMD (0xE9) + +#define SPI_AT_BUF1_LOAD 0x53 +#define SPI_AT_PAGE_ERASE 0x81 +#define SPI_AT_BUF1_WRITE 0x84 +#define SPI_AT_BUF1_PROGRAM 0x88 +#define SPI_AT_STATUS 0xD7 +#define SPI_AT_READY 0x80 + +#define SPI_POLLING_INTERVAL 10 /* in usecs */ +#define SPI_CDRAM_CONT 0x80 + +#define SPI_CDRAM_PCS_PCS0 0x01 +#define SPI_CDRAM_PCS_PCS1 0x02 +#define SPI_CDRAM_PCS_PCS2 0x04 +#define SPI_CDRAM_PCS_PCS3 0x08 +#define SPI_CDRAM_PCS_DSCK 0x10 +#define SPI_CDRAM_PCS_DISABLE_ALL (SPI_CDRAM_PCS_PCS0 | SPI_CDRAM_PCS_PCS1 | \ + SPI_CDRAM_PCS_PCS2 | SPI_CDRAM_PCS_PCS3) +#define SPI_CDRAM_BITSE 0x40 + +#define SPI_SYSTEM_CLK 216000000 /* 216 MHz */ +#define MAX_SPI_BAUD 13500000 /* SPBR = 8 (minimum value), 216MHZ */ + +#define BSPI_Pcs_eUpgSpiPcs2 0 +#define FLASH_SPI_BYTE_ORDER_FIX 1 + +#endif /* _qspi_core_h_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/aisdram-ca9.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/aisdram-ca9.c new file mode 100644 index 00000000000..58a6562d8bf --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/aisdram-ca9.c @@ -0,0 +1,1473 @@ +/* + * DDR23 Denali contoller & DDRPHY init routines. + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: aisdram-ca9.c 596126 2015-10-29 19:53:48Z $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DDR_DEFAULT_CLOCK 333 +#define DDR3_MIN_CLOCK 400 + +#define OTPP_TRIES 10000000 /* # of tries for OTPP */ +#define DEFAULT_OTPCPU_CTRL0 0x00a00600 + +extern void si_mem_setclock(si_t *sih, uint32 ddrclock); + +unsigned int ddr2_init_tab_400[] = { + 0, 0x00000400, + 1, 0x00000000, + 3, 0x00000050, + 4, 0x000000c8, + 5, 0x0c050c02, + 6, 0x04020405, + 7, 0x05031015, + 8, 0x03101504, + 9, 0x05020305, + 10, 0x03006d60, + 11, 0x05020303, + 12, 0x03006d60, + 13, 0x01000003, + 14, 0x05061001, + 15, 0x000b0b06, + 16, 0x030000c8, + 17, 0x00a01212, + 18, 0x060600a0, + 19, 0x00000000, + 20, 0x00003001, + 21, 0x00300c2d, + 22, 0x00050c2d, + 23, 0x00000200, + 24, 0x000a0002, + 25, 0x0002000a, + 26, 0x00020008, + 27, 0x00c80008, + 28, 0x00c80037, + 29, 0x00000037, + 30, 0x03000001, + 31, 0x00030303, + 32, 0x00000000, + 35, 0x00000000, + 36, 0x01000000, + 37, 0x10000000, + 38, 0x00100400, + 39, 0x00000400, + 40, 0x00000100, + 41, 0x00000000, + 42, 0x00000001, + 43, 0x00000000, + 44, 0x000a6300, + 45, 0x00000004, + 46, 0x00040a63, + 47, 0x00000000, + 48, 0x0a630000, + 49, 0x00000004, + 50, 0x00040a63, + 51, 0x00000000, + 52, 0x0a630000, + 53, 0x00000004, + 54, 0x00040a63, + 55, 0x00000000, + 56, 0x0a630000, + 57, 0x00000004, + 58, 0x00040a63, + 59, 0x00000000, + 60, 0x00000000, + 61, 0x00010100, + 62, 0x00000000, + 63, 0x00000000, + 64, 0x00000000, + 65, 0x00000000, + 66, 0x00000000, + 67, 0x00000000, + 68, 0x00000000, + 69, 0x00000000, + 70, 0x00000000, + 71, 0x00000000, + 72, 0x00000000, + 73, 0x00000000, + 74, 0x00000000, + 75, 0x00000000, + 76, 0x00000000, + 77, 0x00000000, + 78, 0x01000200, + 79, 0x02000040, + 80, 0x00400100, + 81, 0x00000200, + 82, 0x01030001, + 83, 0x01ffff0a, + 84, 0x01010101, + 85, 0x03010101, + 86, 0x01000003, + 87, 0x0000010c, + 88, 0x00010000, + 89, 0x00000000, + 90, 0x00000000, + 91, 0x00000000, + 92, 0x00000000, + 93, 0x00000000, + 94, 0x00000000, + 95, 0x00000000, + 96, 0x00000000, + 97, 0x00000000, + 98, 0x00000000, + 99, 0x00000000, + 100, 0x00000000, + 101, 0x00000000, + 102, 0x00000000, + 103, 0x00000000, + 104, 0x00000000, + 105, 0x00000000, + 106, 0x00000000, + 107, 0x00000000, + 108, 0x02020101, + 109, 0x08080404, + 110, 0x03020200, + 111, 0x01000202, + 112, 0x00000200, + 113, 0x00000000, + 114, 0x00000000, + 115, 0x00000000, + 116, 0x19000000, + 117, 0x00000028, + 118, 0x00000000, + 119, 0x00010001, + 120, 0x00010001, + 121, 0x00010001, + 122, 0x00010001, + 123, 0x00010001, + 124, 0x00000000, + 125, 0x00000000, + 126, 0x00000000, + 127, 0x00000000, + 128, 0x001c1c00, + 129, 0x1c1c0001, + 130, 0x00000001, + 131, 0x00000000, + 132, 0x00000000, + 133, 0x00011c1c, + 134, 0x00011c1c, + 135, 0x00000000, + 136, 0x00000000, + 137, 0x001c1c00, + 138, 0x1c1c0001, + 139, 0x00000001, + 140, 0x00000000, + 141, 0x00000000, + 142, 0x00011c1c, + 143, 0x00011c1c, + 144, 0x00000000, + 145, 0x00000000, + 146, 0x001c1c00, + 147, 0x1c1c0001, + 148, 0xffff0001, + 149, 0x00ffff00, + 150, 0x0000ffff, + 151, 0x00000000, + 152, 0x03030303, + 153, 0x03030303, + 156, 0x02006400, + 157, 0x02020202, + 158, 0x02020202, + 160, 0x01020202, + 161, 0x01010064, + 162, 0x01010101, + 163, 0x01010101, + 165, 0x00020101, + 166, 0x00000064, + 167, 0x00000000, + 168, 0x000a0a00, + 169, 0x0c2d0000, + 170, 0x02000200, + 171, 0x02000200, + 172, 0x00000c2d, + 173, 0x00003ce1, + 174, 0x0c2d0505, + 175, 0x02000200, + 176, 0x02000200, + 177, 0x00000c2d, + 178, 0x00003ce1, + 179, 0x02020505, + 180, 0x80000100, + 181, 0x04070303, + 182, 0x0000000a, + 183, 0x00000000, + 184, 0x00000000, + 185, 0x0010ffff, + 186, 0x16070303, + 187, 0x0000000f, + 188, 0x00000000, + 189, 0x00000000, + 190, 0x00000000, + 191, 0x00000000, + 192, 0x00000000, + 193, 0x00000000, + 194, 0x00000204, + 195, 0x00000000, + 196, 0x00000000, + 197, 0x00000000, + 198, 0x00000000, + 199, 0x00000000, + 200, 0x00000000, + 201, 0x00000000, + 202, 0x00000050, + 203, 0x00000050, + 204, 0x00000000, + 205, 0x00000040, + 206, 0x01030301, + 207, 0x00000001, + 0xffffffff +}; + +#ifdef _UNUSED_ +unsigned int ddr3_init_tab[] = { + 14, 0x05051001, + 15, 0x000a0a05, + 36, 0x01000000, + 37, 0x10000000, + 38, 0x00100400, + 39, 0x00000400, + 40, 0x00000100, + 42, 0x00000001, + 61, 0x00010100, + 78, 0x01000200, + 79, 0x02000040, + 80, 0x00400100, + 81, 0x00000200, + 83, 0x01ffff0a, + 84, 0x01010101, + 85, 0x03010101, + 86, 0x01000003, + 87, 0x0000010c, + 88, 0x00010000, + 112, 0x00000200, + 116, 0x19000000, + 117, 0x00000028, + 119, 0x00010001, + 120, 0x00010001, + 121, 0x00010001, + 122, 0x00010001, + 123, 0x00010001, + 130, 0x00000001, + 139, 0x00000001, + 148, 0xffff0001, + 149, 0x00ffff00, + 150, 0x0000ffff, + 152, 0x03030303, + 153, 0x03030303, + 156, 0x02006400, + 157, 0x02020202, + 158, 0x02020202, + 160, 0x01020202, + 161, 0x01010064, + 162, 0x01010101, + 163, 0x01010101, + 165, 0x00020101, + 166, 0x00000064, + 168, 0x000a0a00, + 170, 0x02000200, + 171, 0x02000200, + 175, 0x02000200, + 176, 0x02000200, + 180, 0x80000100, + 181, 0x04070303, + 182, 0x0000000a, + 185, 0x0010ffff, + 187, 0x0000000f, + 194, 0x00000204, + 205, 0x00000040, + 0xffffffff +}; + +unsigned int ddr3_init_tab_666[] = { + 0, 0x00000600, + 3, 0x0001046b, + 4, 0x00028b0b, + 5, 0x0c050c00, + 6, 0x04040405, + 7, 0x05040e14, + 8, 0x040e1404, + 9, 0x0c040405, + 10, 0x03005b68, + 11, 0x0c040404, + 12, 0x03005b68, + 13, 0x01000004, + 16, 0x03000200, + 17, 0x00000f0f, + 18, 0x05050000, + 20, 0x00007801, + 21, 0x00780a20, + 22, 0x00050a20, + 23, 0x00000300, + 24, 0x000a0003, + 25, 0x0000000a, + 27, 0x02000000, + 28, 0x0200005a, + 29, 0x0000005a, + 30, 0x05000001, + 31, 0x00050505, + 44, 0x00022000, + 45, 0x00000046, + 46, 0x00460210, + 48, 0x02100000, + 49, 0x00000046, + 50, 0x00460210, + 52, 0x02100000, + 53, 0x00000046, + 54, 0x00460210, + 56, 0x02100000, + 57, 0x00000046, + 58, 0x00460210, + 82, 0x01010001, + 108, 0x02040108, + 109, 0x08010402, + 110, 0x02020202, + 111, 0x01000201, + 128, 0x00212100, + 129, 0x21210001, + 133, 0x00012121, + 134, 0x00012121, + 137, 0x00212100, + 138, 0x21210001, + 142, 0x00012121, + 143, 0x00012121, + 146, 0x00212100, + 147, 0x21210001, + 169, 0x0a200000, + 172, 0x00000a20, + 173, 0x000032a0, + 174, 0x0a200505, + 177, 0x00000a20, + 178, 0x000032a0, + 179, 0x02020505, + 186, 0x16070303, + 202, 0x00000004, + 203, 0x00000004, + 206, 0x01040401, + 207, 0x00000001, + 0xffffffff +}; + +unsigned int ddr3_init_tab_1333[] = { + 0, 0x00000600, + 1, 0x00000000, + 3, 0x00000086, + 4, 0x0000014e, + 5, 0x12071200, + 6, 0x05040407, + 7, 0x09051821, + 8, 0x05182105, + 9, 0x0c040509, + 10, 0x0400b6d0, + 11, 0x0c040504, + 12, 0x0400b6d0, + 13, 0x01000004, + 14, 0x090a1001, + 15, 0x0013130a, + 16, 0x03000200, + 17, 0x00001e1e, + 18, 0x09090000, + 19, 0x00000000, + 20, 0x0000ea01, + 21, 0x00ea1448, + 22, 0x00051448, + 23, 0x00000400, + 24, 0x00100004, + 25, 0x00000010, + 26, 0x00000000, + 27, 0x02000000, + 28, 0x020000f0, + 29, 0x000000f0, + 30, 0x07000001, + 31, 0x00070707, + 32, 0x00000000, + 35, 0x00000000, + 36, 0x01000000, + 37, 0x10000000, + 38, 0x00100400, + 39, 0x00000400, + 40, 0x00000100, + 41, 0x00000000, + 42, 0x00000001, + 43, 0x00000000, + 44, 0x000a5000, + 45, 0x00100046, + 46, 0x00460a50, + 47, 0x00000010, + 48, 0x0a500000, + 49, 0x00100046, + 50, 0x00460a50, + 51, 0x00000010, + 52, 0x0a500000, + 53, 0x00100046, + 54, 0x00460a50, + 55, 0x00000010, + 56, 0x0a500000, + 57, 0x00100046, + 58, 0x00460a50, + 59, 0x00000010, + 60, 0x00000000, + 61, 0x00010100, + 62, 0x00000000, + 63, 0x00000000, + 64, 0x00000000, + 65, 0x00000000, + 66, 0x00000000, + 67, 0x00000000, + 68, 0x00000000, + 69, 0x00000000, + 70, 0x00000000, + 71, 0x00000000, + 72, 0x00000000, + 73, 0x00000000, + 74, 0x00000000, + 75, 0x00000000, + 76, 0x00000000, + 77, 0x00000000, + 78, 0x01000200, + 79, 0x02000040, + 80, 0x00400100, + 81, 0x00000200, + 82, 0x01000001, + 83, 0x01ffff0a, + 84, 0x01010101, + 85, 0x03010101, + 86, 0x01000003, + 87, 0x0000010c, + 88, 0x00010000, + 89, 0x00000000, + 90, 0x00000000, + 91, 0x00000000, + 92, 0x00000000, + 93, 0x00000000, + 94, 0x00000000, + 95, 0x00000000, + 96, 0x00000000, + 97, 0x00000000, + 98, 0x00000000, + 99, 0x00000000, + 100, 0x00000000, + 101, 0x00000000, + 102, 0x00000000, + 103, 0x00000000, + 104, 0x00000000, + 105, 0x00000000, + 106, 0x00000000, + 107, 0x00000000, + 108, 0x02040108, + 109, 0x08010402, + 110, 0x02020202, + 111, 0x01000201, + 112, 0x00000200, + 113, 0x00000000, + 114, 0x00000000, + 115, 0x00000000, + 116, 0x19000000, + 117, 0x00000028, + 118, 0x00000000, + 119, 0x00010001, + 120, 0x00010001, + 121, 0x00010001, + 122, 0x00010001, + 123, 0x00010001, + 124, 0x00000000, + 125, 0x00000000, + 126, 0x00000000, + 127, 0x00000000, + 128, 0x00232300, + 129, 0x23230001, + 130, 0x00000001, + 131, 0x00000000, + 132, 0x00000000, + 133, 0x00012323, + 134, 0x00012323, + 135, 0x00000000, + 136, 0x00000000, + 137, 0x00232300, + 138, 0x23230001, + 139, 0x00000001, + 140, 0x00000000, + 141, 0x00000000, + 142, 0x00012323, + 143, 0x00012323, + 144, 0x00000000, + 145, 0x00000000, + 146, 0x00232300, + 147, 0x23230001, + 148, 0xffff0001, + 149, 0x00ffff00, + 150, 0x0000ffff, + 151, 0x00000000, + 152, 0x03030303, + 153, 0x03030303, + 156, 0x02006400, + 157, 0x02020202, + 158, 0x02020202, + 160, 0x01020202, + 161, 0x01010064, + 162, 0x01010101, + 163, 0x01010101, + 165, 0x00020101, + 166, 0x00000064, + 167, 0x00000000, + 168, 0x000b0b00, + 169, 0x14480000, + 170, 0x02000200, + 171, 0x02000200, + 172, 0x00001448, + 173, 0x00006568, + 174, 0x14480708, + 175, 0x02000200, + 176, 0x02000200, + 177, 0x00001448, + 178, 0x00006568, + 179, 0x02020708, + 180, 0x80000100, + 181, 0x04070303, + 182, 0x0000000a, + 183, 0x00000000, + 184, 0x00000000, + 185, 0x0010ffff, + 186, 0x1a070303, + 187, 0x0000000f, + 188, 0x00000000, + 189, 0x00000000, + 190, 0x00000000, + 191, 0x00000000, + 192, 0x00000000, + 193, 0x00000000, + 194, 0x00000204, + 195, 0x00000000, + 196, 0x00000000, + 197, 0x00000000, + 198, 0x00000000, + 199, 0x00000000, + 200, 0x00000000, + 201, 0x00000000, + 202, 0x00000007, + 203, 0x00000007, + 204, 0x00000000, + 205, 0x00000040, + 206, 0x00060601, + 207, 0x00000000, + 0xffffffff +}; +#endif /* _UNUSED_ */ + +unsigned int ddr3_init_tab_1600[] = { + 0, 0x00000600, + 1, 0x00000000, + 3, 0x000000a0, + 4, 0x00061a80, + 5, 0x16081600, + 6, 0x06040408, + 7, 0x0b061c27, + 8, 0x061c2706, + 9, 0x0c04060b, + 10, 0x0400db60, + 11, 0x0c040604, + 12, 0x0400db60, + 13, 0x01000004, + 14, 0x0b0c1001, + 15, 0x0017170c, + 16, 0x03000200, + 17, 0x00002020, + 18, 0x0b0b0000, + 19, 0x00000000, + 20, 0x00011801, + 21, 0x01181858, + 22, 0x00051858, + 23, 0x00000500, + 24, 0x00140005, + 25, 0x00000014, + 26, 0x00000000, + 27, 0x02000000, + 28, 0x02000120, + 29, 0x00000120, + 30, 0x08000001, + 31, 0x00080808, + 32, 0x00000000, + 35, 0x00000000, + 36, 0x01000000, + 37, 0x10000000, + 38, 0x00100400, + 39, 0x00000400, + 40, 0x00000100, + 41, 0x00000000, + 42, 0x00000001, + 43, 0x00000000, + 44, 0x000c7000, + 45, 0x00180046, + 46, 0x00460c70, + 47, 0x00000018, + 48, 0x0c700000, + 49, 0x00180046, + 50, 0x00460c70, + 51, 0x00000018, + 52, 0x0c700000, + 53, 0x00180046, + 54, 0x00460c70, + 55, 0x00000018, + 56, 0x0c700000, + 57, 0x00180046, + 58, 0x00460c70, + 59, 0x00000018, + 60, 0x00000000, + 61, 0x00010100, + 62, 0x00000000, + 63, 0x00000000, + 64, 0x00000000, + 65, 0x00000000, + 66, 0x00000000, + 67, 0x00000000, + 68, 0x00000000, + 69, 0x00000000, + 70, 0x00000000, + 71, 0x00000000, + 72, 0x00000000, + 73, 0x00000000, + 74, 0x00000000, + 75, 0x00000000, + 76, 0x00000000, + 77, 0x00000000, + 78, 0x01000200, + 79, 0x02000040, + 80, 0x00400100, + 81, 0x00000200, + 82, 0x01000001, + 83, 0x01ffff0a, + 84, 0x01010101, + 85, 0x03010101, + 86, 0x01000003, + 87, 0x0000010c, + 88, 0x00010000, + 89, 0x00000000, + 90, 0x00000000, + 91, 0x00000000, + 92, 0x00000000, + 93, 0x00000000, + 94, 0x00000000, + 95, 0x00000000, + 96, 0x00000000, + 97, 0x00000000, + 98, 0x00000000, + 99, 0x00000000, + 100, 0x00000000, + 101, 0x00000000, + 102, 0x00000000, + 103, 0x00000000, + 104, 0x00000000, + 105, 0x00000000, + 106, 0x00000000, + 107, 0x00000000, + 108, 0x02040108, + 109, 0x08010402, + 110, 0x02020202, + 111, 0x01000201, + 112, 0x00000200, + 113, 0x00000000, + 114, 0x00000000, + 115, 0x00000000, + 116, 0x19000000, + 117, 0x00000028, + 118, 0x00000000, + 119, 0x00010001, + 120, 0x00010001, + 121, 0x00010001, + 122, 0x00010001, + 123, 0x00010001, + 124, 0x00000000, + 125, 0x00000000, + 126, 0x00000000, + 127, 0x00000000, + 128, 0x00232300, + 129, 0x23230001, + 130, 0x00000001, + 131, 0x00000000, + 132, 0x00000000, + 133, 0x00012323, + 134, 0x00012323, + 135, 0x00000000, + 136, 0x00000000, + 137, 0x00232300, + 138, 0x23230001, + 139, 0x00000001, + 140, 0x00000000, + 141, 0x00000000, + 142, 0x00012323, + 143, 0x00012323, + 144, 0x00000000, + 145, 0x00000000, + 146, 0x00232300, + 147, 0x23230001, + 148, 0xffff0001, + 149, 0x00ffff00, + 150, 0x0000ffff, + 151, 0x00000000, + 152, 0x03030303, + 153, 0x03030303, + 156, 0x02006400, + 157, 0x02020202, + 158, 0x02020202, + 160, 0x01020202, + 161, 0x01010064, + 162, 0x01010101, + 163, 0x01010101, + 165, 0x00020101, + 166, 0x00000064, + 167, 0x00000000, + 168, 0x000b0b00, + 169, 0x18580000, + 170, 0x02000200, + 171, 0x02000200, + 172, 0x00001858, + 173, 0x000079b8, + 174, 0x1858080a, + 175, 0x02000200, + 176, 0x02000200, + 177, 0x00001858, + 178, 0x000079b8, + 179, 0x0202080a, + 180, 0x80000100, + 181, 0x04070303, + 182, 0x0000000a, + 183, 0x00000000, + 184, 0x00000000, + 185, 0x0010ffff, + 186, 0x1c070303, + 187, 0x0000000f, + 188, 0x00000000, + 189, 0x00000000, + 190, 0x00000000, + 191, 0x00000000, + 192, 0x00000000, + 193, 0x00000000, + 194, 0x00000204, + 195, 0x00000000, + 196, 0x00000000, + 197, 0x00000000, + 198, 0x00000000, + 199, 0x00000000, + 200, 0x00000000, + 201, 0x00000000, + 202, 0x00000008, + 203, 0x00000008, + 204, 0x00000000, + 205, 0x00000040, + 206, 0x00070701, + 207, 0x00000000, + 0xffffffff +}; + +static void +ddr_regs_init(si_t *sih, ddrcregs_t *ddr, unsigned int ddr_table[]) +{ + osl_t *osh; + uint32 reg_num, reg_val; + int idx = 0; + + osh = si_osh(sih); + while ((reg_num = ddr_table[idx++]) != DDR_TABLE_END) { + reg_val = ddr_table[idx++]; + W_REG(osh, &ddr->control[reg_num], reg_val); + } +} + +int rewrite_mode_registers(void *sih) +{ + osl_t *osh; + ddrcregs_t *ddr; + int nRet = 0; + int j = 100; + uint32 val; + + osh = si_osh((si_t *)sih); + ddr = (ddrcregs_t *)si_setcore((si_t *)sih, NS_DDR23_CORE_ID, 0); + if (!ddr) { + nRet = 1; + goto out; + } + + val = R_REG(osh, &ddr->control[89]); + val &= ~(1 << 18); + W_REG(osh, &ddr->control[89], val); + + /* Set mode register for MR0, MR1, MR2 and MR3 write for all chip selects */ + val = (1 << 17) | (1 << 24) | (1 << 25); + W_REG(osh, &ddr->control[43], val); + + /* Trigger Mode Register Write(MRW) sequence */ + val |= (1 << 25); + W_REG(osh, &ddr->control[43], val); + + do { + if (R_REG(osh, &ddr->control[89]) & (1 << 18)) { + break; + } + --j; + } while (j); + + if (j == 0 && (R_REG(osh, &ddr->control[89]) & (1 << 18)) == 0) { + printf("Error: DRAM mode registers write failed\n"); + nRet = 1; + }; +out: + return nRet; +} + +static int +_check_cmd_done(void) +{ + unsigned int k; + uint32 st; + + for (k = 0; k < OTPP_TRIES; k++) { + st = R_REG(NULL, (uint32 *)DMU_OTP_CPU_STS); + if (st & OTPCPU_STS_CMD_DONE_MASK) { + break; + } + } + if (k >= OTPP_TRIES) { + printf("%s: %d _check_cmd_done: %08x\n", __FUNCTION__, __LINE__, k); + return -1; + } + return 0; +} + +static int +_issue_read(unsigned int row, uint32 *val) +{ + uint32 ctrl1, ctrl0; + uint32 start; + uint32 cmd; + uint32 fuse; + uint32 cof; + uint32 prog_en; + uint32 mode; + int rv; + + W_REG(NULL, (uint32 *)DMU_OTP_CPU_ADDR, row); + + start = (1 << OTPCPU_CTRL1_START_SHIFT) & OTPCPU_CTRL1_START_MASK; + cmd = (OTPCPU_CMD_READ << OTPCPU_CTRL1_CMD_SHIFT) & OTPCPU_CTRL1_CMD_MASK; + fuse = (1 << OTPCPU_CTRL1_2XFUSE_SHIFT) & OTPCPU_CTRL1_2XFUSE_MASK; + cof = (2 << OTPCPU_CTRL1_COF_SHIFT) & OTPCPU_CTRL1_COF_MASK; + prog_en = (0 << OTPCPU_CTRL1_PROG_EN_SHIFT) & OTPCPU_CTRL1_PROG_EN_MASK; + mode = (1 << OTPCPU_CTRL1_ACCESS_MODE_SHIFT) & OTPCPU_CTRL1_ACCESS_MODE_MASK; + + ctrl1 = cmd; + ctrl1 |= fuse; + ctrl1 |= cof; + ctrl1 |= prog_en; + ctrl1 |= mode; + + ctrl1 |= start; + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL1, ctrl1); + ctrl0 = DEFAULT_OTPCPU_CTRL0; + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL0, ctrl0); + + /* Check if cmd_done bit is asserted */ + rv = _check_cmd_done(); + if (rv) { + printf("%s: %d _check_cmd_done: %08x\n", __FUNCTION__, __LINE__, rv); + return -1; + } + + *val = R_REG(NULL, (uint32 *)DMU_OTP_CPU_READ_DATA); + + return 0; +} + +static int +_issue_prog_dis(void) +{ + uint32 ctrl1, ctrl0; + uint32 start; + uint32 cmd; + uint32 fuse; + uint32 cof; + uint32 prog_en; + uint32 mode; + int rv; + + W_REG(NULL, (uint32 *)DMU_OTP_CPU_ADDR, 0); + + start = (1 << OTPCPU_CTRL1_START_SHIFT) & OTPCPU_CTRL1_START_MASK; + cmd = (OTPCPU_CMD_PROG_DIS << OTPCPU_CTRL1_CMD_SHIFT) & OTPCPU_CTRL1_CMD_MASK; + fuse = (1 << OTPCPU_CTRL1_2XFUSE_SHIFT) & OTPCPU_CTRL1_2XFUSE_MASK; + cof = (1 << OTPCPU_CTRL1_COF_SHIFT) & OTPCPU_CTRL1_COF_MASK; + prog_en = (1 << OTPCPU_CTRL1_PROG_EN_SHIFT) & OTPCPU_CTRL1_PROG_EN_MASK; + mode = (2 << OTPCPU_CTRL1_ACCESS_MODE_SHIFT) & OTPCPU_CTRL1_ACCESS_MODE_MASK; + + ctrl1 = cmd; + ctrl1 |= fuse; + ctrl1 |= cof; + ctrl1 |= prog_en; + ctrl1 |= mode; + + ctrl1 |= start; + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL1, ctrl1); + ctrl0 = DEFAULT_OTPCPU_CTRL0; + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL0, ctrl0); + + /* Check if cmd_done bit is asserted */ + rv = _check_cmd_done(); + if (rv) { + printf("%s: %d _check_cmd_done: %08x\n", __FUNCTION__, __LINE__, rv); + return -1; + } + + ctrl1 &= ~start; + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL1, ctrl1); + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CTRL0, ctrl0); + + return 0; +} + +int +bcm5301x_otp_read_dword(unsigned int wn, uint32 *data) +{ + uint32 cpu_cfg; + int rv; + + /* Check if CPU mode is enabled */ + cpu_cfg = R_REG(NULL, (uint32 *)DMU_OTP_CPU_CONFIG); + if (!(cpu_cfg & OTPCPU_CFG_CPU_MODE_MASK)) { + cpu_cfg |= ((1 << OTPCPU_CFG_CPU_MODE_SHIFT) & OTPCPU_CFG_CPU_MODE_MASK); + W_REG(NULL, (uint32 *)DMU_OTP_CPU_CONFIG, cpu_cfg); + } + cpu_cfg = R_REG(NULL, (uint32 *)DMU_OTP_CPU_CONFIG); + + /* Issue ProgDisable command */ + rv = _issue_prog_dis(); + if (rv) { + printf("%s: %d _issue_prog_dis failed: %d\n", __FUNCTION__, __LINE__, rv); + return -1; + } + + /* Issue ReadWord command */ + rv = _issue_read(wn, data); + if (rv) { + printf("%s: %d _issue_read failed: %d\n", __FUNCTION__, __LINE__, rv); + return -1; + } + + return 0; +} + +int +Program_Digital_Core_Power_Voltage(si_t *sih) +{ +#define ROW_NUMBER 0x8 +#define MDC_DIV 0x8 +#define DIGITAL_POWER_CORE_VOLTAGE_1_POINT_05V 0x520E003C +#define DIGITAL_POWER_CORE_VOLTAGE_1V 0x520E0020 +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_975V 0x520E0018 +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9625V 0x520E0014 +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_95V 0x520E0010 +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9375V 0x520E000C +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_925V 0x520E0008 +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9125V 0x520E0004 +#define DIGITAL_POWER_CORE_VOLTAGE_POINT_9V 0x520E0000 +#define AVS_CODE_RS 17 +#define AVS_CODE_MASK 7 + + osl_t *osh; + chipcommonbregs_t *chipcb; + uint32 avs_code = 0; + int retval = 0; + char *vol_str = NULL; + + osh = si_osh(sih); + chipcb = (chipcommonbregs_t *)si_setcore(sih, NS_CCB_CORE_ID, 0); + if (chipcb == NULL) { + retval = -1; + printf("%s: %d chipcb null %d\n", __FUNCTION__, __LINE__, retval); + return retval; + } + + if (CHIPID(sih->chip) == BCM4707_CHIP_ID || CHIPID(sih->chip) == BCM47094_CHIP_ID) { + if (sih->chippkg == BCM4708_PKG_ID) { + /* access internal regulator phy by setting the MDC/MDIO + * bus frequency to 125/8 + */ + W_REG(osh, &chipcb->pcu_mdio_mgt, MDC_DIV); + udelay(500); + /* this is 0.9 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9375V); + printf("Digital core power voltage set to 0.9375V\n"); + return retval; + } else if ((CHIPID(sih->chip) == BCM47094_CHIP_ID) && + (sih->chippkg == BCM4709_PKG_ID)) { + W_REG(osh, &chipcb->pcu_mdio_mgt, MDC_DIV); + udelay(500); + /* this is 1.05 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_1_POINT_05V); + printf("Digital core power voltage set to 1.05V\n"); + return retval; + } + } + + retval = bcm5301x_otp_read_dword(ROW_NUMBER, &avs_code); + if (retval != 0) { + printf("%s: %d failed bcm5301x_otp_read_dword: %d\n", + __FUNCTION__, __LINE__, retval); + return retval; + } + + /* bits 17 - 19 is the avs code */ + avs_code = (avs_code >> AVS_CODE_RS) & AVS_CODE_MASK; + + /* access internal regulator phy by setting the MDC/MDIO bus frequency to 125/8 */ + W_REG(osh, &chipcb->pcu_mdio_mgt, MDC_DIV); + udelay(500); + + switch (avs_code) { + case 0: + /* this is 1 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_1V); + vol_str = "1.0"; + break; + case 1: + /* this is 0.975 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_975V); + vol_str = "0.975"; + break; + case 2: + /* this is 0.9625 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9625V); + vol_str = "0.9625"; + break; + case 3: + /* this is 0.95 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_95V); + vol_str = "0.95"; + break; + case 4: + /* this is 0.9375 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9375V); + vol_str = "0.9375"; + break; + case 5: + /* this is 0.925 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_925V); + vol_str = "0.925"; + break; + case 6: + /* this is 0.9125 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9125V); + vol_str = "0.9125"; + break; + case 7: + /* this is 0.9 V */ + W_REG(osh, &chipcb->pcu_mdio_cmd, DIGITAL_POWER_CORE_VOLTAGE_POINT_9V); + vol_str = "0.9"; + break; + default: + printf("%s: %d unrecognized avs_code %d\n", __FUNCTION__, __LINE__, avs_code); + break; + } + + if (vol_str) + printf("Digital core power voltage set to %sV\n", vol_str); + + return retval; +} + +void +c_ddr_init(unsigned long ra) +{ + si_t *sih; + osl_t *osh; + void *regs; + int ddrtype_ddr3 = 0; + int bootdev; + struct nvram_header *nvh = NULL; + uintptr flbase; + uint32 off, sdram_config, sdram_ncdl; + uint32 config_refresh, sdram_refresh; + ddrcregs_t *ddr; + chipcommonbregs_t *chipcb; + uint32 val, val1; + int i; + uint32 ddrclock = DDR_DEFAULT_CLOCK, clkval; + uint32 params, connect, ovride, status; + uint32 wire_dly[4] = {0}; + + /* Basic initialization */ + sih = (si_t *)osl_init(); + osh = si_osh(sih); +#ifdef BCMDBG + printf("\n==================== CFE Boot Loader ====================\n"); +#endif + + Program_Digital_Core_Power_Voltage(sih); + + regs = (void *)si_setcore(sih, NS_DDR23_CORE_ID, 0); + if (regs) { + ddrtype_ddr3 = ((si_core_sflags(sih, 0, 0) & DDR_TYPE_MASK) == DDR_STAT_DDR3); + } + if (ddrtype_ddr3) { + chipcb = (chipcommonbregs_t *)si_setcore(sih, NS_CCB_CORE_ID, 0); + if (chipcb) { + /* Configure DDR voltage to 1.5V */ + val = R_REG(osh, &chipcb->pcu_1v8_1v5_vregcntl); + val = (val & ~PCU_VOLTAGE_SELECT_MASK) | PCU_VOLTAGE_SELECT_1V5; + W_REG(osh, &chipcb->pcu_1v8_1v5_vregcntl, val); + + /* Enable LDO voltage output */ + val = PCU_AOPC_PWRDIS_SEL; + W_REG(osh, &chipcb->pcu_aopc_control, val); + val |= PCU_AOPC_PWRDIS_LATCHEN; + W_REG(osh, &chipcb->pcu_aopc_control, val); + val1 = R_REG(osh, &chipcb->pcu_status); + val1 &= PCU_PWR_EN_STRAPS_MASK; + val |= (~(val1 << 1) & PCU_AOPC_PWRDIS_MASK); + val &= ~PCU_AOPC_PWRDIS_DDR; + W_REG(osh, &chipcb->pcu_aopc_control, val); + } + } + + /* Set DDR clock */ + ddr = (ddrcregs_t *)si_setcore(sih, NS_DDR23_CORE_ID, 0); + if (!ddr) + goto out; + val = R_REG(osh, (uint32 *)DDR_S1_IDM_RESET_CONTROL); + if ((val & AIRC_RESET) == 0) + val = R_REG(osh, &ddr->control[0]); + else + val = 0; + if (val & DDRC00_START) { + clkval = *((uint32 *)(0x1000 + BISZ_OFFSET - 4)); + if (clkval) { + val = AIRC_RESET; + W_REG(osh, (uint32 *)DDR_S1_IDM_RESET_CONTROL, val); + W_REG(osh, (uint32 *)DDR_S2_IDM_RESET_CONTROL, val); + ddrclock = clkval; + si_mem_setclock(sih, ddrclock); + } + } else { + /* DDR PHY doesn't support 333MHz for DDR3, so set the clock to 400 by default. */ + ddrclock = DDR3_MIN_CLOCK; + si_mem_setclock(sih, ddrclock); + } + + /* Find NVRAM for the sdram_config variable */ + bootdev = soc_boot_dev((void *)sih); +#ifdef NFLASH_SUPPORT + if (bootdev == SOC_BOOTDEV_NANDFLASH) { + flbase = SI_NS_NANDFLASH; + goto embedded_nv; + } + else +#endif /* NFLASH_SUPPORT */ + { + /* bootdev == SOC_BOOTDEV_SFLASH */ + flbase = SI_NS_NORFLASH; + off = FLASH_MIN; + while (off <= SI_NS_FLASH_WINDOW) { + nvh = (struct nvram_header *)(flbase + off - MAX_NVRAM_SPACE); + if (R_REG(osh, &nvh->magic) == NVRAM_MAGIC) + break; + off += DEF_NVRAM_SPACE; + nvh = NULL; + }; + } +#ifdef NFLASH_SUPPORT +embedded_nv: +#endif + if (nvh == NULL) { + nvh = (struct nvram_header *)(flbase + 1024); + if (R_REG(osh, &nvh->magic) != NVRAM_MAGIC) { + goto out; + } + } + config_refresh = R_REG(osh, &nvh->config_refresh); + sdram_config = config_refresh & 0xffff; + sdram_refresh = (config_refresh >> 16) & 0xffff; + sdram_ncdl = R_REG(osh, &nvh->config_ncdl); +#ifdef BCMDBG + printf("%s: sdram_config=0x%04x sdram_ncdl=0x%08x\n", + __FUNCTION__, sdram_config, sdram_ncdl); +#endif + + /* Take DDR23 core out of reset */ + W_REG(osh, (uint32 *)DDR_S1_IDM_RESET_CONTROL, 0); + W_REG(osh, (uint32 *)DDR_S2_IDM_RESET_CONTROL, 0); + /* Set the ddr_ck to 400 MHz, 2x memc clock */ + val = R_REG(osh, (uint32 *)DDR_S1_IDM_IO_CONTROL_DIRECT); + val &= ~(0xfff << 16); + val |= (0x190 << 16); + W_REG(osh, (uint32 *)DDR_S1_IDM_IO_CONTROL_DIRECT, val); + + /* Wait for DDR PHY up */ + for (i = 0; i < 0x19000; i++) { + val = R_REG(osh, &ddr->phy_control_rev); + if (val != 0) + break; /* DDR PHY is up */ + } + if (i == 0x19000) { +#ifdef BCMDBG + printf("Recalibrating DDR PHY...\n"); +#endif + si_watchdog(sih, 1); + while (1); + } + + /* Change PLL divider values inside PHY */ + W_REG(osh, &ddr->phy_control_plldividers, 0x00000c10); /* high sku ? */ + if (ddrclock != DDR_DEFAULT_CLOCK) { + /* SHAMOO related DDR PHY init change */ +#ifdef CONFIG_DDR_LONG_PREAMBLE + params = DDR40_PHY_PARAM_USE_VTT | + DDR40_PHY_PARAM_ODT_LATE | + DDR40_PHY_PARAM_ADDR_CTL_ADJUST_0 | + DDR40_PHY_PARAM_ADDR_CTL_ADJUST_1 | + DDR40_PHY_PARAM_MAX_ZQ | + DDR40_PHY_PARAM_LONG_PREAMBLE; +#else + params = DDR40_PHY_PARAM_USE_VTT | + DDR40_PHY_PARAM_ODT_LATE | + DDR40_PHY_PARAM_ADDR_CTL_ADJUST_0 | + DDR40_PHY_PARAM_ADDR_CTL_ADJUST_1 | + DDR40_PHY_PARAM_MAX_ZQ; +#endif /* CONFIG_DDR_LONG_PREAMBLE */ + if (ddrtype_ddr3) { + /* DDR3, 1.5v */ + params |= DDR40_PHY_PARAM_VDDO_VOLT_0; + } + else { + /* DDR2, 1.8v */ + params |= DDR40_PHY_PARAM_VDDO_VOLT_1; + } + connect = 0x01CF7FFF; + ovride = 0x00077FFF; + status = ddr40_phy_init(ddrclock, params, ddrtype_ddr3, + wire_dly, connect, ovride, (uint32_t)DDR_PHY_CONTROL_REGS_REVISION); + if (status != DDR40_PHY_RETURN_OK) { + printf("Error: ddr40_phy_init failed with error 0x%x\n", status); + return; + } + } else { + /* Set LDO output voltage control to 1.00 * VDDC, and enable PLL */ + val = (1 << 4); + W_REG(osh, &ddr->phy_control_pllconfig, val); + + /* Wait for PLL locked */ + for (i = 0; i < 0x1400; i++) { + val = R_REG(osh, &ddr->phy_control_pllstatus); + if (val & 0x1) + break; + } + if (i == 0x1400) { + printf("DDR PHY PLL lock failed\n"); + goto out; + } + + W_REG(osh, &ddr->phy_ln0_rddata_dly, 3); /* high sku? */ + + /* Write 2 if ddr2, 3 if ddr3 */ + /* Set preamble mode according to DDR type, + * and length of write preamble to 1.5 DQs, 0.75 DQ + */ + if (ddrtype_ddr3) + val = 1; + else + val = 0; +#ifdef CONFIG_DDR_LONG_PREAMBLE + val |= 2; +#endif + W_REG(osh, &ddr->phy_ln0_wr_premb_mode, val); + + /* Initiate a PVT calibration cycle */ + W_REG(osh, &ddr->phy_control_zq_pvt_compctl, (1 << 20)); + + /* Initiate auto calibration and apply the results to VDLs */ + W_REG(osh, &ddr->phy_control_vdl_calibrate, 0x08000101); /* high sku? */ + + /* Wait for Calibration lock done */ + for (i = 0; i < 0x1400; i++) { + val = R_REG(osh, &ddr->phy_control_vdl_calibsts); + if (val & 0x1) + break; + } + if (i == 0x1400) { + printf("DDR PHY auto calibration timed out\n"); + goto out; + } + + if (!(val & 0x2)) { +#ifdef BCMDBG + printf("Need re-calibrating...\n"); +#endif + si_watchdog(sih, 1); + while (1); + } + } + + if (ddrtype_ddr3) { + ddr_regs_init(sih, ddr, ddr3_init_tab_1600); + } else { + ddr_regs_init(sih, ddr, ddr2_init_tab_400); + } + if (ddrclock == DDR_DEFAULT_CLOCK) { + /* High SKU, DDR-1600 */ + /* Auto initialization fails at DDRCLK 800 MHz, manually override */ + W_REG(osh, &ddr->phy_ln0_vdl_ovride_byte1_r_n, 0x00010120); + W_REG(osh, &ddr->phy_ln0_vdl_ovride_byte0_bit_rd_en, 0x0001000d); + W_REG(osh, &ddr->phy_ln0_vdl_ovride_byte1_bit_rd_en, 0x00010020); + } + + /* Set Tref */ + if (sdram_refresh == 0) + sdram_refresh = (0x1858 * ddrclock) / 800; + + val = R_REG(osh, &ddr->control[21]); + val &= ~0x3fff; + val |= sdram_refresh & 0x3fff; + W_REG(osh, &ddr->control[21], val); + + val = R_REG(osh, &ddr->control[22]); + val &= ~0x3fff; + val |= sdram_refresh & 0x3fff; + W_REG(osh, &ddr->control[22], val); + + if (sdram_config) { + uint32 cas, wrlat; + + /* Check reduce mode */ + val = R_REG(osh, &ddr->control[87]); + if (sdram_config & 0x80) + val |= (1 << 8); + /* FIXME: we will enable clearing the reduce mode bit + * once confirmed with the board design team. + */ + W_REG(osh, &ddr->control[87], val); + + val = R_REG(osh, &ddr->control[82]); + /* Check 8-bank mode */ + if (sdram_config & 0x40) + val &= ~(3 << 8); + else { + /* default 4 banks */ + val &= ~(3 << 8); + val |= (1 << 8); + } + /* Defaul row_diff=0; Check column diff */ + val &= ~(0x707 << 16); + val |= ((sdram_config & 0x700) << 16); + W_REG(osh, &ddr->control[82], val); + + /* Now do CAS latency settings */ + cas = sdram_config & 0x1f; + if (cas > 5) + wrlat = cas - (cas-4)/2; + else + wrlat = cas - 1; + + val = R_REG(osh, &ddr->control[5]); + val &= ~0x3f1f3f00; + val = val | (cas << 9) | (cas << 25) | (wrlat << 16); + W_REG(osh, &ddr->control[5], val); + + val = R_REG(osh, &ddr->control[6]); + val &= ~0x1f; + val |= wrlat; + W_REG(osh, &ddr->control[6], val); + + val = R_REG(osh, &ddr->control[174]); + val &= ~0x1f3f; + val |= (wrlat << 8) | (cas-1); + W_REG(osh, &ddr->control[174], val); + + val = R_REG(osh, &ddr->control[186]); + val &= ~0xff000000; + val |= ((cas+17) << 24); + W_REG(osh, &ddr->control[186], val); + + if (ddrtype_ddr3) { + val = R_REG(osh, &ddr->control[44]); + val &= ~0xf000; + val |= ((cas-4) << 12); + W_REG(osh, &ddr->control[44], val); + + val = R_REG(osh, &ddr->control[45]); + val &= ~0x00380000; + if (cas > 9) + val |= ((cas-8) << 19); + else if (cas > 7) + val |= ((cas-7) << 19); + else if (cas >= 6) + val |= ((cas-6) << 19); + W_REG(osh, &ddr->control[45], val); + + val = R_REG(osh, &ddr->control[206]); + val &= ~0x00001f00; + val |= ((wrlat-1) << 8); + W_REG(osh, &ddr->control[206], val); + } else { + val = R_REG(osh, &ddr->control[44]); + val &= ~0xf000; + val |= (cas << 12); + W_REG(osh, &ddr->control[44], val); + } + } + + /* Start the DDR */ + val = R_REG(osh, &ddr->control[0]); + val |= DDRC00_START; + W_REG(osh, &ddr->control[0], val); + while (!(R_REG(osh, &ddr->control[89]) & DDR_INT_INIT_DONE)); +#ifdef BCMDBG + printf("%s: DDR PLL locked\n", __FUNCTION__); +#endif + + W_REG(osh, &ddr->phy_ln0_rddata_dly, 3); /* high sku? */ + + /* Run the SHMOO */ + if (ddrtype_ddr3 && ddrclock > DDR3_MIN_CLOCK) { + status = do_shmoo((void *)sih, DDR_PHY_CONTROL_REGS_REVISION, 0, + ((26 << 16) | (16 << 8) | DO_ALL_SHMOO), 0x1000000); + if (status != SHMOO_NO_ERROR) { + printf("Error: do_shmoo failed with error 0x%x\n", status); +#ifdef BCMDBG + goto out; +#else + hnd_cpu_reset(sih); +#endif + } + } + +out: + asm("mov pc,%0" : : "r"(ra) : "cc"); +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/aisdram_ca9.S b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/aisdram_ca9.S new file mode 100644 index 00000000000..92828712cd8 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/aisdram_ca9.S @@ -0,0 +1,2221 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: aisdram_ca9.S 654158 2016-08-11 09:30:01Z $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __arm__ +#error __arm__ is NOT defined +#endif + +/* Routine begin/end macro */ +#if defined(__thumb__) +#define FUNC(x) THUMBLEAF(x) +#else +#define FUNC(x) LEAF(x) +#endif /* __thumb__ */ + + .text + +FUNC(ddr_init_ca9) + mov r9,r0 /* ddr control register base */ + mov r8,r1 + mov r7,r2 + + /* ddr2 or ddr3 */ + ldr r3,=0x18108500 + ldr r0,[r3] + ldr r2,=DDR_STAT_DDR3 + and r0,r0,r2 + cmp r0,r2 + bne chk_bootdev + + /* Configure DDR3 voltage to 1.5V */ + ldr r1,=0x1800c02c + ldr r2,=0x00000200 + str r2,[r1] + ldr r3,[r1] + /* Enable LDO voltage output */ + ldr r1,=0x1800c020 /* pcu_aopc_control */ + ldr r2,=0x80000000 + str r2,[r1] + ldr r3,[r1] + ldr r2,=0x80000001 + str r2,[r1] + ldr r3,[r1] + ldr r4,=0x1800c024 /* pcu_status */ + ldr r3,[r4] + bic r3,r3,#0xf + lsl r3,r3,#1 + ldr r4,=0x1e + bic r4,r4,r3 + orr r2,r2,r3 + bic r2,r2,#4 + str r2,[r1] + ldr r3,[r1] + +chk_bootdev: + mov r6,#0x0 + ldr r0,=SISF_NS_BOOTDEV_ROM + cmp r0,r7 + bne find_flashnvram + +find_otpnvram: + ldr r0,=SI_ENUM_BASE_DEFAULT /* r0: core regs SI base address */ + ldr r4,[r0,#CC_CAPABILITIES] /* r4: capabitilies */ + and r4,r4,#CC_CAP_OTPSIZE + cmp r4,#0 + beq find_flashnvram + + /* Skip OTP initialization here since it was already done in pcie_phy_init */ + lsr r2,r4,#CC_CAP_OTPSIZE_SHIFT /* Get OTP size */ + adrl r1,otp_sizes + lsl r2,r2,#0x2 + ldr r3,[r1,r2] /* Get the OTP size from otp_sizes table (in bytes) */ + + cmp r3,#0x0 /* skip zero size */ + beq find_flashnvram + ldr r1,[r0,#CC_OTPST] + and r1,r1,#OTPS_READY + cmp r1,#0x0 /* 0: OTP is not ready for whatever reason */ + beq find_flashnvram + add r2,r3,r0 /* Seek to the end of OTP region */ + /* Scan entire OTP from END -> BEGIN to find first + * matching nvram entry */ + sub r2,r2,#2 +1: + add r4,r2,#CC_SROM_OTP + ldrh r1,[r4] + lsl r1,r1,#0x10 + sub r2,r2,#2 + add r4,r2,#CC_SROM_OTP + ldrh r3,[r4] + orr r1,r1,r3 + ldr r4,=NVRAM_MAGIC + cmp r1,r4 + beq 1f + cmp r0,r2 + blt 1b + b find_flashnvram + /* no nvram from OTP */ + + /* Get sdram params from OTP 16bits at a time */ +1: + add r2,r2,#12 + add r4,r2,#CC_SROM_OTP + ldrh r1,[r4] + add r2,r2,#2 + add r4,r2,#CC_SROM_OTP + ldrh r3,[r4] + lsl r3,r3,#0x10 + orr r6,r1,r3 /* sdram_config + sdram_rehash */ + add r2,r2,#2 + add r4,r2,#CC_SROM_OTP + ldrh r1,[r4] + add r2,r2,#2 + add r4,r2,#CC_SROM_OTP + ldrh r3,[r4] + lsl r3,r3,#0x10 + orr r5,r1,r3 /* sdram_ncdl */ + +find_flashnvram: + ldr r0,=SI_NS_NANDFLASH + ldr r1,=SISF_NS_BOOTDEV_NAND + cmp r1,r7 + beq nand_embedded_nv + + ldr r0,=SI_NS_NORFLASH + ldr r1,=MAX_NVRAM_SPACE + sub r0,r0,r1 + ldr r1,=FLASH_MIN + ldr r2,=SI_NS_FLASH_WINDOW + ldr r3,=NVRAM_MAGIC + +1: add r4,r0,r1 + ldr r8,[r4] + cmp r8,r3 + beq read_config + lsl r1,r1,#1 + cmp r1,r2 + ble 1b + + /* Try embedded NVRAM at 4KB and 1KB as last resorts */ + ldr r0,=SI_NS_NORFLASH +nand_embedded_nv: + add r4,r0,#0x1000 + ldr r8,[r4] + cmp r8,r3 + beq read_config + + add r4,r0,#0x400 + ldr r8,[r4] + cmp r8,r3 + beq read_config + +2: ldr r0,=0x0 /* if we have sdram params from OTP then use it */ + cmp r6,r0 + bne set_ddr_clock + +no_sdram_params: + ldr r6,=0x0 + ldr r5,=0x0 + b set_ddr_clock + +read_config: + ldr r6,[r4,#12] /* Pick up sdram_config & sdram_refresh */ + ldr r5,[r4,#16] /* Pick up sdram_ncdl */ + +set_ddr_clock: + ldr r0,=DDRC00_START + ldr r1,[r9,#DDRC_CONTROL00] + and r1,r1,r0 + cmp r1,r0 + bne init_ddrphy /* The first time */ + ldr r1,=0x1000 + ldr r0,=BISZ_OFFSET + add r1,r1,r0 + sub r1,r1,#4 + ldr r0,=0x0 + ldr r2,[r1] + cmp r2,r0 + beq init_ddrphy /* No ddrclk specified */ + + ldr r3,=DDR_TABLE_END + adrl r4,ddr_clk_tab +1: ldr r1,[r4] + cmp r1,r3 + beq init_ddrphy + cmp r1,r2 + beq chg_ddr_clock + add r4,r4,#12 + b 1b + +chg_ddr_clock: + /* Put the controller to reset mode first */ + ldr r1,=0x18108800 + ldr r2,=0x00000001 + str r2,[r1] + ldr r1,=0x18109800 + str r2,[r1] + + ldr r0,=CRU_CLKSET_KEY + ldr r1,=0xea68 + str r1,[r0] + + ldr r0,=LCPLL_NDIV_INT + ldr r1,[r0] + ldr r2,=0xf00fffff + and r1,r1,r2 + ldr r2,[r4,#4] + orr r1,r1,r2 + str r1,[r0] + ldr r0,=LCPLL_CHX_MDIV + ldr r1,[r0] + ldr r2,=0x000000ff + and r1,r1,r2 + ldr r2,[r4,#8] + orr r1,r1,r2 + str r1,[r0] + +en_change: + ldr r0,=LCPLL_LOAD_EN_CH + ldr r1,[r0] + orr r1,r1,#0x7 + str r1,[r0] + and r1,r1,#0xfffffff8 + str r1,[r0] + ldr r0,=CRU_CLKSET_KEY + ldr r1,=0x0 + str r1,[r0] + +init_ddrphy: + mov r8,r9 /* save r9 */ + + ldr r1,=0x18108800 + ldr r2,=0x00000000 + str r2,[r1] + ldr r1,=0x18109800 + str r2,[r1] + + ldr r1,=0x18108408 + ldr r2,[r1] + ldr r3,=0xf000ffff + and r2,r2,r3 + orr r2,r2,#0x01900000 + str r2,[r1] + + ldr r9,=0x18010800 + ldr r1,=0x0 + ldr r3,=0x00019000 + +wait_for_ddr_phy_up: + cmp r3,r1 + beq ddr_phy_rdy + sub r3,r3,#0x1 + ldr r2,=0x0 + ldr r2,[r9] + cmp r2,r1 + bne ddr_phy_rdy + b wait_for_ddr_phy_up +ddr_phy_rdy: + + /* Change PLL divider values inside PHY */ + ldr r1,=0x1801081c + ldr r2,=0x00000c10 + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010814 + ldr r2,=0x00000010 + str r2,[r1] + ldr r3,[r9] + + ldr r4,=0x18010810 + ldr r1,=0x1 + ldr r3,=0x00001400 + +wait_for_ddr_phy_pll_lock: + cmp r3,r1 + beq ddr_phy_pll_lock_done + sub r3,r3,#0x1 + ldr r2,=0x0 + ldr r2,[r4] + and r2,r2,#0x1 + cmp r2,r1 + beq ddr_phy_pll_lock_done + b wait_for_ddr_phy_pll_lock +ddr_phy_pll_lock_done: + + ldr r1,=0x18010b60 + ldr r2,=0x00000003 + str r2,[r1] + ldr r3,[r9] + + /* Write 2 if ddr2, 3 if ddr3 */ + ldr r1,=0x18108500 + ldr r3,[r1] + ldr r2,=0x00000001 + and r3,r2,r3 + orr r2,r3,#0x2 + ldr r1,=0x18010bac + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x1801083c + ldr r2,=0x00100000 + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010848 + ldr r2,=0x08000101 + str r2,[r1] + ldr r3,[r9] + + ldr r4,=0x1801084C + ldr r1,=0x1 + ldr r3,=0x00001400 + +wait_for_ddr_phy_calib_lock: + cmp r3,r1 + beq ddr_phy_calib_lock_done + sub r3,r3,#0x1 + ldr r2,=0x0 + ldr r2,[r4] + and r2,r2,#0x1 + cmp r2,r1 + beq ddr_phy_calib_lock_done + b wait_for_ddr_phy_calib_lock +ddr_phy_calib_lock_done: + + ldr r4,=0x1801084C + ldr r1,=0x2 + ldr r2,[r4] + and r2,r2,#0x2 + cmp r2,r1 + beq ddr_cntrl_prog + +calib_override: + ldr r1,=0x18010834 + ldr r2,=0x0001003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a04 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a10 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a14 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a18 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a1c + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a20 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a24 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a28 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a2c + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a30 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010aa4 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ab0 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ab4 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ab8 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010abc + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ac0 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ac4 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ac8 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010acc + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010ad0 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a08 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a0c + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010aa8 + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010aac + ldr r2,=0x0003003f + str r2,[r1] + ldr r3,[r9] + +ddr_cntrl_prog: + + /* correct Vtt voltage */ + ldr r1,=0x18010864 + ldr r2,=0x01d7ffff + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010868 + str r2,[r1] + ldr r3,[r9] + + mov r9,r8 /* restore r9 */ + +init_regs: + + /* ddr2 or ddr3 */ + ldr r8,=0x18108500 + ldr r0,[r8] + ldr r2,=DDR_STAT_DDR3 + and r0,r0,r2 + cmp r0,r2 + beq ddr3_init + +ddr2_init: + mov ip,lr /* save lr across calls */ + adrl r0,ddr2_init_tab + bl ddr_init_regs + mov lr,ip /* restore lr */ + b chparams + +ddr3_init: + mov ip,lr /* save lr across calls */ + adrl r0,ddr3_init_tab + bl ddr_init_regs + mov lr,ip /* restore lr */ + +chparams: + ldr r0,=0x0 + cmp r6,r0 + beq turnon /* No sdram params, use default values */ + +chtref: + lsr r2,r6,#16 + cmp r2,r0 + beq chhalf + ldr r1,[r9,#DDRC_CONTROL21] + ldr r3,=0x3fff + bic r1,r1,r3 + orr r1,r1,r2 + str r1,[r9,#DDRC_CONTROL21] + ldr r1,[r9,#DDRC_CONTROL22] + ldr r3,=0x3fff + bic r1,r1,r3 + orr r1,r1,r2 + str r1,[r9,#DDRC_CONTROL22] + +chhalf: + ldr r1,=0x80 + and r1,r1,r6 + cmp r1,r0 + beq ch8banks +setreduc: + ldr r1,[r9,#DDRC_CONTROL87] + ldr r2,=0x00000100 + orr r1,r1,r2 + str r1,[r9,#DDRC_CONTROL87] + +ch8banks: + ldr r1,=0x40 + and r1,r1,r6 + cmp r1,r0 + beq do4banks +do8banks: + ldr r1,[r9,#DDRC_CONTROL82] + ldr r2,=~0x00000300 + and r1,r1,r2 + str r1,[r9,#DDRC_CONTROL82] + b docols +do4banks: + ldr r1,[r9,#DDRC_CONTROL82] + ldr r2,=~0x00000300 + and r1,r1,r2 + ldr r2,=0x00000100 + orr r1,r1,r2 + str r1,[r9,#DDRC_CONTROL82] + +docols: + ldr r1,[r9,#DDRC_CONTROL82] + ldr r2,=~0x07070000 + and r1,r1,r2 + ldr r2,=0x700 + and r2,r2,r6 + lsl r2,r2,#16 + orr r1,r1,r2 + str r1,[r9,#DDRC_CONTROL82] + +docaslat: + ldr r0,=0x1f + and r0,r0,r6 /* cas latency */ + sub r1,r0,#1 /* wrlat */ + cmp r0,#6 + blt 1f + sub r1,r0,#4 + lsr r1,r1,#1 + sub r1,r0,r1 /* wrlat */ +1: + ldr r2,[r9,#DDRC_CONTROL05] + ldr r3,=~0x3f1f3f00 + and r2,r2,r3 + lsl r3,r0,#9 /* cas << 9 */ + orr r2,r2,r3 + lsl r3,r0,#25 /* cas << 25 */ + orr r2,r2,r3 + lsl r3,r1,#16 /* wrlat << 16 */ + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL05] + ldr r2,[r9,#DDRC_CONTROL06] + ldr r3,=~0x0000001f + and r2,r2,r3 + orr r2,r2,r1 + str r2,[r9,#DDRC_CONTROL06] + + ldr r2,[r9,#DDRC_CONTROL174] + ldr r3,=~0x00001f3f + and r2,r2,r3 + lsl r3,r1,#8 + orr r2,r2,r3 + sub r3,r0,#1 + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL174] + + ldr r2,[r9,#DDRC_CONTROL44] + ldr r3,=~0x0000f000 + and r2,r2,r3 + mov r3,r0 + lsl r3,r3,#12 + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL44] + + ldr r2,[r9,#DDRC_CONTROL186] + ldr r3,=~0xff000000 + and r2,r2,r3 + add r3,r0,#17 + lsl r3,r3,#24 + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL186] + + ldr r8,=0x18108500 + ldr r3,[r8] + ldr r2,=DDR_STAT_DDR3 + and r3,r3,r2 + cmp r3,r2 + bne turnon + + ldr r2,[r9,#DDRC_CONTROL44] + ldr r3,=~0x0000f000 + and r2,r2,r3 + sub r3,r0,#4 + lsl r3,r3,#12 + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL44] + ldr r2,[r9,#DDRC_CONTROL45] + ldr r3,=~0x00380000 + and r2,r2,r3 + sub r3,r0,#8 + cmp r0,#9 + bgt 1f + sub r3,r0,#7 + cmp r0,#7 + bgt 1f + sub r3,r0,#6 +1: + lsl r3,r3,#19 + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL45] + + ldr r2,[r9,#DDRC_CONTROL206] + ldr r3,=~0x00001f00 + and r2,r2,r3 + sub r3,r1,#1 + lsl r3,r3,#8 + orr r2,r2,r3 + str r2,[r9,#DDRC_CONTROL206] + +turnon: + ldr r0,=DDRC00_START + ldr r1,[r9,#DDRC_CONTROL00] + orr r1,r1,r0 + str r1,[r9,#DDRC_CONTROL00] + +poll_ddr_ctrl: + ldr r0,[r9,#DDRC_CONTROL89] + ldr r2,=DDR_INT_INIT_DONE + and r0,r2,r0 + cmp r0,r2 + bne poll_ddr_ctrl + + ldr r1,=0x18010b60 + ldr r2,=0x00000003 + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a00 + ldr r2,=0x00010120 + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010a74 + ldr r2,=0x0001000d + str r2,[r1] + ldr r3,[r9] + + ldr r1,=0x18010b14 + ldr r2,=0x00010020 + str r2,[r1] + ldr r3,[r9] + + mov pc,lr + .ltorg + + .align 4 +ddr_clk_tab: + .word 333, 0x07800000, 0x1e0f1200 + .word 389, 0x08c00000, 0x23121200 + .word 400, 0x08000000, 0x20101000 + .word 533, 0x08000000, 0x20100c00 + .word 666, 0x07800000, 0x1e0f0900 + .word 775, 0x07c00000, 0x20100800 + .word 800, 0x08000000, 0x20100800 + .word DDR_TABLE_END + + .align 4 +ddr2_init_tab: + .word 0, 0x00000400 + .word 1, 0x00000000 + .word 3, 0x00000050 + .word 4, 0x000000c8 + .word 5, 0x0c050c02 + .word 6, 0x04020405 + .word 7, 0x05031015 + .word 8, 0x03101504 + .word 9, 0x05020305 + .word 10, 0x03006d60 + .word 11, 0x05020303 + .word 12, 0x03006d60 + .word 13, 0x01000003 + .word 14, 0x05061001 + .word 15, 0x000b0b06 + .word 16, 0x030000c8 + .word 17, 0x00a01212 + .word 18, 0x060600a0 + .word 19, 0x00000000 + .word 20, 0x00003001 + .word 21, 0x00300c2d + .word 22, 0x00050c2d + .word 23, 0x00000200 + .word 24, 0x000a0002 + .word 25, 0x0002000a + .word 26, 0x00020008 + .word 27, 0x00c80008 + .word 28, 0x00c80037 + .word 29, 0x00000037 + .word 30, 0x03000001 + .word 31, 0x00030303 + .word 36, 0x01000000 + .word 37, 0x10000000 + .word 38, 0x00100400 + .word 39, 0x00000400 + .word 40, 0x00000100 + .word 41, 0x00000000 + .word 42, 0x00000001 + .word 43, 0x00000000 + .word 44, 0x000a6300 + .word 45, 0x00000004 + .word 46, 0x00040a63 + .word 47, 0x00000000 + .word 48, 0x0a630000 + .word 49, 0x00000004 + .word 50, 0x00040a63 + .word 51, 0x00000000 + .word 52, 0x0a630000 + .word 53, 0x00000004 + .word 54, 0x00040a63 + .word 55, 0x00000000 + .word 56, 0x0a630000 + .word 57, 0x00000004 + .word 58, 0x00040a63 + .word 59, 0x00000000 + .word 60, 0x00000000 + .word 61, 0x00010100 + .word 78, 0x01000200 + .word 79, 0x02000040 + .word 80, 0x00400100 + .word 81, 0x00000200 + .word 82, 0x01030001 + .word 83, 0x01ffff0a + .word 84, 0x01010101 + .word 85, 0x03010101 + .word 86, 0x01000003 + .word 87, 0x0000010c + .word 88, 0x00010000 + .word 108, 0x02020101 + .word 109, 0x08080404 + .word 110, 0x03020200 + .word 111, 0x01000202 + .word 112, 0x00000200 + .word 116, 0x19000000 + .word 117, 0x00000028 + .word 118, 0x00000000 + .word 119, 0x00010001 + .word 120, 0x00010001 + .word 121, 0x00010001 + .word 122, 0x00010001 + .word 123, 0x00010001 + .word 128, 0x001c1c00 + .word 129, 0x1c1c0001 + .word 130, 0x00000001 + .word 133, 0x00011c1c + .word 134, 0x00011c1c + .word 137, 0x001c1c00 + .word 138, 0x1c1c0001 + .word 139, 0x00000001 + .word 142, 0x00011c1c + .word 143, 0x00011c1c + .word 144, 0x00000000 + .word 145, 0x00000000 + .word 146, 0x001c1c00 + .word 147, 0x1c1c0001 + .word 148, 0xffff0001 + .word 149, 0x00ffff00 + .word 150, 0x0000ffff + .word 151, 0x00000000 + .word 152, 0x03030303 + .word 153, 0x03030303 + .word 156, 0x02006400 + .word 157, 0x02020202 + .word 158, 0x02020202 + .word 160, 0x01020202 + .word 161, 0x01010064 + .word 162, 0x01010101 + .word 163, 0x01010101 + .word 165, 0x00020101 + .word 166, 0x00000064 + .word 167, 0x00000000 + .word 168, 0x000a0a00 + .word 169, 0x0c2d0000 + .word 170, 0x02000200 + .word 171, 0x02000200 + .word 172, 0x00000c2d + .word 173, 0x00003ce1 + .word 174, 0x0c2d0505 + .word 175, 0x02000200 + .word 176, 0x02000200 + .word 177, 0x00000c2d + .word 178, 0x00003ce1 + .word 179, 0x02020505 + .word 180, 0x80000100 + .word 181, 0x04070303 + .word 182, 0x0000000a + .word 185, 0x0010ffff + .word 186, 0x16070303 + .word 187, 0x0000000f + .word 194, 0x00000204 + .word 202, 0x00000050 + .word 203, 0x00000050 + .word 204, 0x00000000 + .word 205, 0x00000040 + .word 206, 0x01030301 + .word 207, 0x00000001 + .word DDR_TABLE_END + + .align 4 +ddr3_init_tab: + .word 0, 0x00000600 + .word 1, 0x00000000 + .word 3, 0x000000a0 + .word 4, 0x00061a80 + .word 5, 0x16081600 + .word 6, 0x06040408 + .word 7, 0x0b061c27 + .word 8, 0x061c2706 + .word 9, 0x0c04060b + .word 10, 0x0400db60 + .word 11, 0x0c040604 + .word 12, 0x0400db60 + .word 13, 0x01000004 + .word 14, 0x0b0c1001 + .word 15, 0x0017170c + .word 16, 0x03000200 + .word 17, 0x00002020 + .word 18, 0x0b0b0000 + .word 19, 0x00000000 + .word 20, 0x00011801 + .word 21, 0x01181858 + .word 22, 0x00051858 + .word 23, 0x00000500 + .word 24, 0x00140005 + .word 25, 0x00000014 + .word 26, 0x00000000 + .word 27, 0x02000000 + .word 28, 0x02000120 + .word 29, 0x00000120 + .word 30, 0x08000001 + .word 31, 0x00080808 + .word 32, 0x00000000 + .word 35, 0x00000000 + .word 36, 0x01000000 + .word 37, 0x10000000 + .word 38, 0x00100400 + .word 39, 0x00000400 + .word 40, 0x00000100 + .word 41, 0x00000000 + .word 42, 0x00000001 + .word 43, 0x00000000 + .word 44, 0x000c7000 + .word 45, 0x00180046 + .word 46, 0x00460c70 + .word 47, 0x00000018 + .word 48, 0x0c700000 + .word 49, 0x00180046 + .word 50, 0x00460c70 + .word 51, 0x00000018 + .word 52, 0x0c700000 + .word 53, 0x00180046 + .word 54, 0x00460c70 + .word 55, 0x00000018 + .word 56, 0x0c700000 + .word 57, 0x00180046 + .word 58, 0x00460c70 + .word 59, 0x00000018 + .word 60, 0x00000000 + .word 61, 0x00010100 + .word 62, 0x00000000 + .word 63, 0x00000000 + .word 64, 0x00000000 + .word 65, 0x00000000 + .word 66, 0x00000000 + .word 67, 0x00000000 + .word 68, 0x00000000 + .word 69, 0x00000000 + .word 70, 0x00000000 + .word 71, 0x00000000 + .word 72, 0x00000000 + .word 73, 0x00000000 + .word 74, 0x00000000 + .word 75, 0x00000000 + .word 76, 0x00000000 + .word 77, 0x00000000 + .word 78, 0x01000200 + .word 79, 0x02000040 + .word 80, 0x00400100 + .word 81, 0x00000200 + .word 82, 0x01000001 + .word 83, 0x01ffff0a + .word 84, 0x01010101 + .word 85, 0x03010101 + .word 86, 0x01000003 + .word 87, 0x0000010c + .word 88, 0x00010000 + .word 89, 0x00000000 + .word 90, 0x00000000 + .word 91, 0x00000000 + .word 92, 0x00000000 + .word 93, 0x00000000 + .word 94, 0x00000000 + .word 95, 0x00000000 + .word 96, 0x00000000 + .word 97, 0x00000000 + .word 98, 0x00000000 + .word 99, 0x00000000 + .word 100, 0x00000000 + .word 101, 0x00000000 + .word 102, 0x00000000 + .word 103, 0x00000000 + .word 104, 0x00000000 + .word 105, 0x00000000 + .word 106, 0x00000000 + .word 107, 0x00000000 + .word 108, 0x02040108 + .word 109, 0x08010402 + .word 110, 0x02020202 + .word 111, 0x01000201 + .word 112, 0x00000200 + .word 113, 0x00000000 + .word 114, 0x00000000 + .word 115, 0x00000000 + .word 116, 0x19000000 + .word 117, 0x00000028 + .word 118, 0x00000000 + .word 119, 0x00010001 + .word 120, 0x00010001 + .word 121, 0x00010001 + .word 122, 0x00010001 + .word 123, 0x00010001 + .word 124, 0x00000000 + .word 125, 0x00000000 + .word 126, 0x00000000 + .word 127, 0x00000000 + .word 128, 0x00232300 + .word 129, 0x23230001 + .word 130, 0x00000001 + .word 131, 0x00000000 + .word 132, 0x00000000 + .word 133, 0x00012323 + .word 134, 0x00012323 + .word 135, 0x00000000 + .word 136, 0x00000000 + .word 137, 0x00232300 + .word 138, 0x23230001 + .word 139, 0x00000001 + .word 140, 0x00000000 + .word 141, 0x00000000 + .word 142, 0x00012323 + .word 143, 0x00012323 + .word 144, 0x00000000 + .word 145, 0x00000000 + .word 146, 0x00232300 + .word 147, 0x23230001 + .word 148, 0xffff0001 + .word 149, 0x00ffff00 + .word 150, 0x0000ffff + .word 151, 0x00000000 + .word 152, 0x03030303 + .word 153, 0x03030303 + .word 156, 0x02006400 + .word 157, 0x02020202 + .word 158, 0x02020202 + .word 160, 0x01020202 + .word 161, 0x01010064 + .word 162, 0x01010101 + .word 163, 0x01010101 + .word 165, 0x00020101 + .word 166, 0x00000064 + .word 167, 0x00000000 + .word 168, 0x000b0b00 + .word 169, 0x18580000 + .word 170, 0x02000200 + .word 171, 0x02000200 + .word 172, 0x00001858 + .word 173, 0x000079b8 + .word 174, 0x1858080a + .word 175, 0x02000200 + .word 176, 0x02000200 + .word 177, 0x00001858 + .word 178, 0x000079b8 + .word 179, 0x0202080a + .word 180, 0x80000100 + .word 181, 0x04070303 + .word 182, 0x0000000a + .word 183, 0x00000000 + .word 184, 0x00000000 + .word 185, 0x0010ffff + .word 186, 0x1c070303 + .word 187, 0x0000000f + .word 188, 0x00000000 + .word 189, 0x00000000 + .word 190, 0x00000000 + .word 191, 0x00000000 + .word 192, 0x00000000 + .word 193, 0x00000000 + .word 194, 0x00000204 + .word 195, 0x00000000 + .word 196, 0x00000000 + .word 197, 0x00000000 + .word 198, 0x00000000 + .word 199, 0x00000000 + .word 200, 0x00000000 + .word 201, 0x00000000 + .word 202, 0x00000008 + .word 203, 0x00000008 + .word 204, 0x00000000 + .word 205, 0x00000040 + .word 206, 0x00070701 + .word 207, 0x00000000 + .word DDR_TABLE_END + +/* OTP sizes in bytes */ +otp_sizes: + .word 0 + .word 256 /* 2048 bits: 32X64 */ + .word 512 /* 4096 bits: 2*32X64 */ + .word 1024 /* 8192 bits: 4*32X64 */ + .word 512 /* 4096 bits: 64X64 */ + .word 768 /* 6144 bits: 5 32X64 */ + .word 0 /* 512 bits: dont care */ + .word 128 /* 1024 bits: 8X64 */ + +END(ddr_init_ca9) + +FUNC(ddr_init_ca7) + mov r9,r0 @ shift register base to 0x18007400 + add r9,r9,#0x400 @ ssince 53573 DDR controller address shift 1K + mov ip,lr @ save lr across calls + +chk_bootdev_53573: @ to determine embedded nvram address + ldr r1,=0x18010c40 @ get ddr type from bit[4] of + ldr r2,=0x7 @ gci chipstatus reg 7 + str r2,[r1] + ldr r1,=0x18010e04 + ldr r7,[r1] @ save bootdev in r7 + + ldr r0,=SI_BCM53573_NANDFLASH @ r0 = 0x30000000 + ldr r3,=SI_BCM53573_BOOTDEV_MASK + and r4,r3,r7 + ldr r3,=SI_BCM53573_BOOTDEV_NOR + cmp r4,r3 + bne embedded_nv_53573 + + ldr r0,=SI_BCM53573_NORFLASH + ldr r1,=MAX_NVRAM_SPACE + sub r0,r0,r1 + ldr r1,=FLASH_MIN + ldr r2,=SI_BCM53573_NORFLASH_WINDOW + ldr r3,=NVRAM_MAGIC + +1: add r4,r0,r1 + ldr r5,[r4] + cmp r5,r3 + beq read_config_53573 + + lsl r1,r1,#1 + cmp r1,r2 + ble 1b + + ldr r0,=SI_BCM53573_NORFLASH @ r0 = 0x1c000000 + + /* Try embedded NVRAM at 4KB and 1KB as last resorts */ +embedded_nv_53573: + ldr r3,=NVRAM_MAGIC + add r4,r0,#0x1000 + ldr r5,[r4] + cmp r5,r3 + beq read_config_53573 + + add r4,r0,#0x400 + ldr r5,[r4] + cmp r5,r3 + beq read_config_53573 + +no_sdram_params_53573: + /* No nvram, pick up some defaults */ + ldr r6,=0x1c6 @ setup sdram_config to 0x1c6 + ldr r5,=0x0 + + b get_ddr_clock_53573 +read_config_53573: + ldr r6,[r4,#12] @ Pick up sdram_config & sdram_refresh + ldr r5,[r4,#16] @ Pick up sdram_ncdl + +get_ddr_clock_53573: + ldr r0,=DDRC00_START + ldr r1,[r9,#DDRC_CONTROL00] + and r1,r1,r0 + cmp r1,r0 + bne set_ddr_clock_default_53573 @ The first time + + ldr r1,=0x1000 + ldr r0,=BISZ_OFFSET + add r1,r1,r0 + sub r1,r1,#4 + ldr r0,=0x0 + ldr r2,[r1] @ retrieve ddr clk from memory + + cmp r2,r0 + beq set_ddr_clock_default_53573 /* No ddrclk specified */ +2: + ldr r3,=DDR_TABLE_END + adrl r4,ddr_clk_tab_53573 +1: ldr r1,[r4] @r4 now hold ddr clock sequence entry + cmp r1,r3 + beq set_ddr_clock_default_53573 + cmp r1,r2 + beq chg_ddr_pll_53573 + add r4,r4,#16 @ table entry 16 bytes + b 1b +set_ddr_clock_default_53573: + ldr r2,=392 @ set r2 to 392MHz for ddr2 + + ldr r3,=533 + and r0,r7,#SI_BCM53573_DDRTYPE_MASK @ gci chipstatus 7 already in r7 + ldr r1,=SI_BCM53573_DDRTYPE_DDR3 + cmp r0,r1 + moveq r2,r3 @ set r2 to 533MHz for ddr3 + b 2b @ to find the clock entry + +chg_ddr_pll_53573: + mov r10,r2 @ save DDR clock in r10 + add r4,r4,#4 @ shift r4 to next entry + +Adjust_Fvco: + ldr r0,=0x18012660 @ switch to PMU PLL control 27 for setting nfrac + ldr r1,=27 + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r4] + str r1,[r0] + add r4,r4,#4 + + ldr r0,=0x18012660 @ switch to PMU PLL control 26 for setting ndiv + ldr r1,=26 + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + ldr r2,=0x000fffff + and r1,r1,r2 + ldr r2,[r4] + orr r1,r1,r2 + str r1,[r0] + add r4,r4,#4 + + ldr r0,=0x18012600 @update PLL with Fvco settings + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x1800002c @ wait until DDR PLL being locked + ldr r1,=0x4 +1: ldr r2,[r0] + and r2,r2,r1 + cmp r2,r1 + bne 1b + +adjust_post_divisor: + ldr r0,=0x18012660 @ switch to PMU PLL control 25 for setting post-divisor + ldr r1,=25 + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + ldr r2,=0x0000ffff + and r1,r1,r2 + ldr r2,[r4] + orr r1,r1,r2 + str r1,[r0] + + ldr r0,=0x18012664 @ load post-divisor setting + ldr r1,[r0] + orr r1,r1,#0x300 + str r1,[r0] + + ldr r0,=0x18012600 @ update PLL with Fvco settings + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x0 @ wait 7.5us for clock switch + ldr r1,=0x2000 +1: add r0,r0,#1 + cmp r0,r1 + ble 1b + + ldr r0,=0x18012664 @ lock post-divisor setting + ldr r1,[r0] + bic r1,r1,#0x300 + str r1,[r0] + + ldr r0,=0x18012600 @ update PLL with post-divisor settings + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x1800002c @ wait until DDR PLL being locked + ldr r1,=0x4 +1: ldr r2,[r0] + and r2,r2,r1 + cmp r2,r1 + bne 1b + +reset_ddr_core_53573: + ldr r0,=0x18107800 @ reset DDR controller and PHY for new frequency + ldr r1,=0x1 + str r1,[r0] + + ldr r0,=0 @ wait 10 cycles for reset complete + ldr r1,=100 +1: add r0,r0,#1 + cmp r0,r1 + ble 1b + + ldr r0,=0x18107800 @ out of reset DDR controller and PHY + ldr r1,=0 + str r1,[r0] + + ldr r0,=0x4 @ test mem_rst_valid in 0x18007004[2] equal + ldr r2,=0x18007004 @ to 0, for reset completed +1: + ldr r1,[r2] + and r1,r1,r0 + cmp r1,#0x0 + bne 1b + +set_pad_on: @ enable DDR read pad + ldr r0,=0x18007048 + ldr r1,=0x0 + str r1,[r0] + ldr r0,=0x1800704c @ enable pad, ODT resistor matching settings + ldr r1,=0x10101010 + str r1,[r0] + ldr r0,=0x18007048 @ ODT resistor matching settings + ldr r1,=0x00000800 + str r1,[r0] + ldr r0,=0x18007040 @ Turn on PVT controller + ldr r1,=0x80002001 + str r1,[r0] + +set_ddr_reg_53573: + and r8, r6,#0xf @ cas latency saved in r8 + + adrl r0,ddr_init_tab_53573 @ call generic DDR ctrlr init + bl ddr_init_regs + + and r0,r7,#SI_BCM53573_DDRTYPE_MASK @ gci chipstatus 7 already in r7 + ldr r1,=SI_BCM53573_DDRTYPE_DDR3 + cmp r0,r1 + beq set_ddr3_reg_53573 +set_ddr2_reg_53573: + adrl r0,ddr2_init_tab_53573 + bl ddr_init_regs + + ldr r0,=392 + cmp r0,r10 @ DDR clock already saved in r10 + beq set_ddr2_392_reg_53573 + ldr r0,=358 + cmp r0,r10 @ DDR clock already saved in r10 + beq set_ddr2_358_reg_53573 + ldr r0,=318 + cmp r0,r10 @ DDR clock already saved in r10 + beq set_ddr2_318_reg_53573 + +set_ddr2_286_reg_53573: + adrl r0,ddr2_286_init_tab_53573 + bl ddr_init_regs + + adrl r0,ddr2_286_cl5_init_tab_53573 + adrl r1,ddr2_286_cl6_init_tab_53573 + cmp r8,#0x6 + moveq r0,r1 @ r0 will point to either cl5/cl6 table eventually + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr2_318_reg_53573: + adrl r0,ddr2_318_init_tab_53573 + bl ddr_init_regs + + adrl r0,ddr2_318_cl5_init_tab_53573 + adrl r1,ddr2_318_cl6_init_tab_53573 + cmp r8,#0x6 + moveq r0,r1 @ r0 will point to either cl5/cl6 table eventually + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr2_358_reg_53573: + adrl r0,ddr2_358_init_tab_53573 @ ddr2 358 support cl6. merge table together + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr2_392_reg_53573: + adrl r0,ddr2_392_init_tab_53573 @ ddr2 392 support cl6. merge table together + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr3_reg_53573: + adrl r0,ddr3_init_tab_53573 + bl ddr_init_regs + + ldr r0,=533 + cmp r0,r10 @ DDR clock already saved in r10 + beq set_ddr3_533_reg_53573 + ldr r0,=392 + cmp r0,r10 @ DDR clock already saved in r10 + beq set_ddr3_392_reg_53573 + ldr r0,=358 + cmp r0,r10 @ DDR clock already saved in r10 + beq set_ddr3_358_reg_53573 + +set_ddr3_318_reg_53573: + adrl r0,ddr3_318_init_tab_53573 + bl ddr_init_regs + + adrl r0,ddr3_318_cl5_init_tab_53573 + adrl r1,ddr3_318_cl6_init_tab_53573 + cmp r8,#0x6 + moveq r0,r1 @ r0 will point to either cl5/cl6 table eventually + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr3_358_reg_53573: + adrl r0,ddr3_358_init_tab_53573 @ ddr3 358 only support cl6. merge table together + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr3_392_reg_53573: + adrl r0,ddr3_392_init_tab_53573 @ ddr3 392 only support cl6. merge table together + bl ddr_init_regs + + b set_half_bus_width_53573 +set_ddr3_533_reg_53573: + adrl r0,ddr3_533_init_tab_53573 + bl ddr_init_regs + + adrl r0,ddr3_533_cl7_init_tab_53573 + adrl r1,ddr3_533_cl8_init_tab_53573 + cmp r8,#0x8 + moveq r0,r1 @ r0 will point to either cl7/cl8 table eventually + bl ddr_init_regs + +set_half_bus_width_53573: + ldr r1,[r9,#DDRC_CONTROL65] + bic r1,r1,#0x1 @ clear bit [0] by default(32bit) + ldr r2,=0x80 + and r3,r6,r2 + cmp r3,r2 + orreq r1,r1,#0x1 @ set bit [0] for half width(16bit) + str r1,[r9,#DDRC_CONTROL65] +set_bank_53573: + ldr r1,[r9,#DDRC_CONTROL60] + bic r1,r1,#0x300 @ clear bit [9:8] for 8 banks + ldr r2,=0x40 + and r3,r6,r2 + cmp r3,r2 + orrne r1,r1,#0x100 @ set bit [8] for 4 banks + str r1,[r9,#DDRC_CONTROL60] + +set_col_53573: + ldr r1,[r9,#DDRC_CONTROL60] + bic r1,r1,#0x0f000000 + ldr r2,=0x700 + and r3,r6,r2 + lsl r0,r3,#16 + orr r1,r1,r0 + str r1,[r9,#DDRC_CONTROL60] + +set_tref_53573: + ldr r2,=0x10000000 + and r2,r6,r2 + cmp r2,#0 + beq set_trfc_53573 + ldr r1,[r9,#DDRC_CONTROL26] @ half tref cycle + ldr r3,=0x3fff + and r2,r1,r3 + bic r1,r1,r3 + lsr r2,r2,#1 + sub r3,r2,#3 + add r1,r1,r3 + str r1,[r9,#DDRC_CONTROL26] +set_trfc_53573: + ldr r2,=0x3ff0000 + and r2,r6,r2 + cmp r2,#0 + beq start_ddr_53573 + ldr r1,[r9,#DDRC_CONTROL25] + ldr r3,=0x3ff0000 + bic r1,r1,r3 + add r1,r1,r2 + str r1,[r9,#DDRC_CONTROL25] @ add counts to trfc + +start_ddr_53573: + ldr r1,[r9,#DDRC_CONTROL00] + orr r1,r1,#DDRC00_START + str r1,[r9,#DDRC_CONTROL00] + +wait_for_ddr_ready_53573: + /* check 0x18007004 bit 7(mc_rdy_for_cmd) for AXI ready to start transaction */ + ldr r0,=0x80 + ldr r2,=0x18007004 +1: + ldr r1,[r2] + and r1,r1,r0 + cmp r1,r0 + bne 1b + +turn_off_ODT_on_16bit_width: + ldr r2,=0x80 + and r3,r6,r2 + cmp r3,r2 @ value 1 means half width + bne ddr_init_completed_53573 + ldr r0,=0x18007a0c @ turning off ODT + ldr r1,=0x000dd000 + str r1,[r0] + +ddr_init_completed_53573: + mov pc,ip /* back to init */ + .ltorg + + .align 6 +ddr_clk_tab_53573: /* pllcontrol 27(nfrac[19:1]), 26(ndiv, nfrac[0]), 25(mdiv) */ + .word 286, 0x00054ccd, 0x01c00000, 0x10080000 + .word 318, 0x000714fe, 0x01700000, 0x0c060000 + .word 358, 0x0006f333, 0x81a00000, 0x0c060000 + .word 392, 0x00040000, 0x01800000, 0x0a050000 + .word 533, 0x00055555, 0x01a00000, 0x08040000 + .word DDR_TABLE_END + + .align 6 +ddr_init_tab_53573: + .word 1, 0x00000000 + .word 2, 0x00000000 + .word 3, 0x00000000 + .word 4, 0x00000000 + .word 5, 0x00000000 + .word 22, 0x01000202 + .word 34, 0x00010000 + .word 37, 0x00000000 + .word 38, 0x00000000 + .word 40, 0x00200400 + .word 41, 0x01000400 + .word 42, 0x00000180 + .word 43, 0x00000000 + .word 44, 0x00000001 + .word 45, 0x00000000 + .word 46, 0x00000000 + .word 51, 0x00000000 + .word 52, 0x00010100 + .word 53, 0x00000000 + .word 54, 0x00000000 + .word 55, 0x00020000 + .word 56, 0x00400100 + .word 57, 0x01000200 + .word 58, 0x02000040 + .word 59, 0x00000040 + .word 60, 0x01000000 + .word 61, 0x01ffff0a + .word 62, 0x01010101 + .word 63, 0x03010101 + .word 64, 0x0c000001 + .word 65, 0x00000000 + .word 66, 0x00010000 + .word 67, 0x00000000 + .word 68, 0x00000000 + .word 69, 0x00000000 + .word 70, 0x00000000 + .word 71, 0x00000000 + .word 72, 0x00000000 + .word 73, 0x00000000 + .word 74, 0x00000000 + .word 75, 0x00000000 + .word 76, 0x00000000 + .word 77, 0x00000000 + .word 81, 0x00000000 + .word 82, 0x00000000 + .word 83, 0x00000000 + .word 84, 0x0d000000 + .word 85, 0x00000028 + .word 86, 0x00000000 + .word 87, 0x00000000 + .word 88, 0x00000000 + .word 89, 0x00000000 + .word 90, 0x00000000 + .word 91, 0x00000000 + .word 92, 0x00000000 + .word 93, 0x00000000 + .word 94, 0x00000000 + .word 95, 0x00000000 + .word 96, 0x00000000 + .word 97, 0x00000000 + .word 98, 0x00000000 + .word 99, 0x00000000 + .word 100, 0x00000202 + .word 101, 0x00000000 + .word 102, 0x00000000 + .word 103, 0x00000000 + .word 104, 0x00000000 + .word 105, 0x00000000 + .word 106, 0xff03ff00 + .word 108, 0x00000000 + .word 110, 0x02000200 + .word 114, 0x02000200 + .word 115, 0x02000200 + .word 119, 0x000a0301 + .word 120, 0x0000000d + .word 121, 0x00000000 + .word 122, 0x00000000 + .word 123, 0x00000000 + .word 124, 0x00000a00 + .word 125, 0x00000000 + .word 126, 0x000d0000 + .word 127, 0x00000000 + .word 128, 0x00000000 + .word 129, 0x00000000 + .word 130, 0x00000000 + .word 131, 0x00000000 + .word 132, 0x00000000 + .word 133, 0x00000001 + .word 135, 0x00000101 + .word 136, 0x00000000 + .word 137, 0x00000000 + .word 138, 0x00000000 + .word 139, 0x00000000 + .word 140, 0x00000000 + .word 141, 0x00000000 + .word 142, 0x00000000 + .word 143, 0x00000000 + .word 144, 0x00000000 + .word 145, 0x00000000 + .word 146, 0x00000000 + .word 147, 0x00000000 + .word 148, 0x00000000 + .word 149, 0x00000000 + .word 150, 0x00000000 + .word 151, 0x00000000 + .word 153, 0x00010000 + .word 154, 0x00000100 + .word 155, 0x00000101 + .word 156, 0x00010000 + .word 157, 0x00000100 + .word 158, 0x00000000 + .word 159, 0x0003ffff + .word 160, 0x00000000 + .word 161, 0x0003ffff + .word 162, 0x00000000 + .word 163, 0x0003ffff + .word 164, 0x00000000 + .word 165, 0x0003ffff + .word 166, 0x00000000 + .word 167, 0x0003ffff + .word 168, 0x00000000 + .word 169, 0x0003ffff + .word 170, 0x00000000 + .word 171, 0x0003ffff + .word 172, 0x00000000 + .word 173, 0x0003ffff + .word 174, 0x00000000 + .word 175, 0x0003ffff + .word 176, 0x00000000 + .word 177, 0x0003ffff + .word 178, 0x00000000 + .word 179, 0x0003ffff + .word 180, 0x00000000 + .word 181, 0x0003ffff + .word 182, 0x00000000 + .word 183, 0x0003ffff + .word 184, 0x00000000 + .word 185, 0x0003ffff + .word 186, 0x00000000 + .word 187, 0x0003ffff + .word 188, 0x00000000 + .word 189, 0x0303ffff + .word 190, 0xffffffff + .word 191, 0x000f000f + .word 192, 0x00ffff03 + .word 193, 0x000fffff + .word 194, 0x0003000f + .word 195, 0xffffffff + .word 196, 0x000f000f + .word 197, 0x00ffff03 + .word 198, 0x000fffff + .word 199, 0x0003000f + .word 200, 0xffffffff + .word 201, 0x000f000f + .word 202, 0x00ffff03 + .word 203, 0x000fffff + .word 204, 0x0003000f + .word 205, 0xffffffff + .word 206, 0x000f000f + .word 207, 0x00ffff03 + .word 208, 0x000fffff + .word 209, 0x0003000f + .word 210, 0xffffffff + .word 211, 0x000f000f + .word 212, 0x00ffff03 + .word 213, 0x000fffff + .word 214, 0x0003000f + .word 215, 0xffffffff + .word 216, 0x000f000f + .word 217, 0x00ffff03 + .word 218, 0x000fffff + .word 219, 0x0003000f + .word 220, 0xffffffff + .word 221, 0x000f000f + .word 222, 0x00ffff03 + .word 223, 0x000fffff + .word 224, 0x0003000f + .word 225, 0xffffffff + .word 226, 0x000f000f + .word 227, 0x00ffff03 + .word 228, 0x000fffff + .word 256, 0x00000413 + .word 257, 0x00000415 + .word 258, 0x80010088 + .word 261, 0x00004040 + .word 262, 0x00000413 + .word 263, 0x00000415 + .word 264, 0x80010060 + .word 265, 0x00000003 + .word 266, 0x0912007f + .word 267, 0x00004040 + .word 268, 0x00000000 + .word 269, 0x00000000 + .word 270, 0x00000000 + .word 271, 0x00000000 + .word 272, 0x00000000 + .word 273, 0x0000818a + .word 274, 0x0000818a + .word 275, 0x00000000 + .word 276, 0x00000000 + .word 277, 0x4240f000 + .word 278, 0x4240f000 + .word 279, 0x00000000 + .word 280, 0x00000000 + .word 281, 0x00000000 + .word 282, 0x00000000 + .word 283, 0x00000000 + .word 284, 0x00000000 + .word 285, 0x00000000 + .word 286, 0x00000000 + .word 287, 0x00000000 + .word 288, 0x00000413 + .word 289, 0x00000415 + .word 290, 0x80010088 + .word 293, 0x00004040 + .word 294, 0x00000413 + .word 295, 0x00000415 + .word 296, 0x80010060 + .word 297, 0x00000003 + .word 298, 0x0912007f + .word 299, 0x00004040 + .word 300, 0x00000000 + .word 301, 0x00000000 + .word 302, 0x00000000 + .word 303, 0x00000000 + .word 304, 0x00000000 + .word 305, 0x0000818a + .word 306, 0x0000818a + .word 307, 0x00000000 + .word 308, 0x00000000 + .word 309, 0x4240f000 + .word 310, 0x4240f000 + .word 311, 0x00000000 + .word 312, 0x00000000 + .word 313, 0x00000000 + .word 314, 0x00000000 + .word 315, 0x00000000 + .word 316, 0x00000000 + .word 317, 0x00000000 + .word 318, 0x00000000 + .word 319, 0x00000000 + .word 320, 0x00000413 + .word 321, 0x00000415 + .word 322, 0x80010088 + .word 325, 0x00004040 + .word 326, 0x00000413 + .word 327, 0x00000415 + .word 328, 0x80010060 + .word 329, 0x00000003 + .word 330, 0x0912007f + .word 331, 0x00004040 + .word 332, 0x00000000 + .word 333, 0x00000000 + .word 334, 0x00000000 + .word 335, 0x00000000 + .word 336, 0x00000000 + .word 337, 0x0000818a + .word 338, 0x0000818a + .word 339, 0x00000000 + .word 340, 0x00000000 + .word 341, 0x4240f000 + .word 342, 0x4240f000 + .word 343, 0x00000000 + .word 344, 0x00000000 + .word 345, 0x00000000 + .word 346, 0x00000000 + .word 347, 0x00000000 + .word 348, 0x00000000 + .word 349, 0x00000000 + .word 350, 0x00000000 + .word 351, 0x00000000 + .word 352, 0x00000413 + .word 353, 0x00000415 + .word 354, 0x80010088 + .word 357, 0x00004040 + .word 358, 0x00000413 + .word 359, 0x00000415 + .word 360, 0x80010060 + .word 361, 0x00000003 + .word 362, 0x0912007f + .word 363, 0x00004040 + .word 364, 0x00000000 + .word 365, 0x00000000 + .word 366, 0x00000000 + .word 367, 0x00000000 + .word 368, 0x00000000 + .word 369, 0x0000818a + .word 370, 0x0000818a + .word 371, 0x00000000 + .word 372, 0x00000000 + .word 373, 0x4240f000 + .word 374, 0x4240f000 + .word 375, 0x00000000 + .word 376, 0x00000000 + .word 377, 0x00000000 + .word 378, 0x00000000 + .word 379, 0x00000000 + .word 380, 0x00000000 + .word 381, 0x00000000 + .word 382, 0x00000000 + .word 383, 0x00000000 + .word 384, 0x00000000 + .word 387, 0x00000000 + .word DDR_TABLE_END + + .align 6 +ddr2_init_tab_53573: + .word 0, 0x00000400 + .word 7, 0x0000682b + .word 11, 0x00000036 + .word 16, 0x02020608 + .word 19, 0x02020203 + .word 20, 0x03002475 + .word 27, 0x00000409 + .word 28, 0x00020002 + .word 29, 0x000a000a + .word 30, 0x00080002 + .word 31, 0x00080002 + .word 33, 0x001300c8 + .word 35, 0x03030300 + .word 36, 0x00000003 + .word 39, 0x20000100 + .word 48, 0x00000040 + .word 50, 0x00000000 + .word 78, 0x03000000 + .word 116, 0x00000812 + .word 117, 0x0000285a + .word 134, 0x00c800c8 + .word 152, 0x02020101 + .word 386, 0x00000005 + .word DDR_TABLE_END + + .align 6 +ddr2_286_init_tab_53573: + .word 6, 0x0000dfdb + .word 8, 0x0000003a + .word 9, 0x00000090 + .word 10, 0x00007302 + .word 14, 0x0d120302 + .word 15, 0x020d0503 + .word 17, 0x04020306 + .word 18, 0x03004e59 + .word 21, 0x05050003 + .word 23, 0x03040a01 + .word 24, 0x00000306 + .word 25, 0x00250100 + .word 26, 0x001108b6 + .word 32, 0x002800c8 + .word 107, 0x0c0c0000 + .word 109, 0x0200116c + .word 111, 0x116c0200 + .word 112, 0x0000571c + .word 259, 0x00000003 + .word 260, 0x08120033 + .word 291, 0x00000003 + .word 292, 0x08120033 + .word 323, 0x00000003 + .word 324, 0x08120033 + .word 355, 0x00000003 + .word 356, 0x08120033 + .word 385, 0x00000005 + .word DDR_TABLE_END + + .align 6 +ddr2_286_cl5_init_tab_53573: + .word 12, 0x00040a00 + .word 13, 0x0400040a + .word 47, 0x00085300 + .word 49, 0x00400253 + .word 79, 0x01000503 + .word 80, 0x00000001 + .word 113, 0x08120405 + .word 118, 0x02020405 + .word 229, 0x0304000f + .word 230, 0x00000304 + .word DDR_TABLE_END + + .align 6 +ddr2_286_cl6_init_tab_53573: + .word 12, 0x00050c00 + .word 13, 0x0400050c + .word 47, 0x00086300 + .word 49, 0x00400263 + .word 79, 0x02000503 + .word 80, 0x00000002 + .word 113, 0x08120506 + .word 118, 0x02020506 + .word 229, 0x0405000f + .word 230, 0x00000405 + .word DDR_TABLE_END + + .align 6 +ddr2_318_init_tab_53573: + .word 6, 0x0000f805 + .word 8, 0x00000040 + .word 9, 0x0000009f + .word 10, 0x00007f02 + .word 14, 0x0f140402 + .word 15, 0x020f0503 + .word 17, 0x04020306 + .word 18, 0x030056ce + .word 21, 0x05050003 + .word 23, 0x03040a01 + .word 24, 0x00000306 + .word 25, 0x00290100 + .word 26, 0x001109a8 + .word 32, 0x002c00c8 + .word 107, 0x0c0d0000 + .word 109, 0x02001350 + .word 111, 0x13500200 + .word 112, 0x00006090 + .word 259, 0x00000004 + .word 260, 0x0a12002d + .word 291, 0x00000004 + .word 292, 0x0a12002d + .word 323, 0x00000004 + .word 324, 0x0a12002d + .word 355, 0x00000004 + .word 356, 0x0a12002d + .word 385, 0x00000006 + .word DDR_TABLE_END + + .align 6 +ddr2_318_cl5_init_tab_53573: + .word 12, 0x00040a00 + .word 13, 0x0400040a + .word 47, 0x00085300 + .word 49, 0x00400253 + .word 79, 0x01000503 + .word 80, 0x00000001 + .word 113, 0x08120405 + .word 118, 0x02020405 + .word 229, 0x0304000f + .word 230, 0x00000304 + .word DDR_TABLE_END + + .align 6 +ddr2_318_cl6_init_tab_53573: + .word 12, 0x00050c00 + .word 13, 0x0400050c + .word 47, 0x00086300 + .word 49, 0x00400263 + .word 79, 0x02000503 + .word 80, 0x00000002 + .word 113, 0x08120506 + .word 118, 0x02020506 + .word 229, 0x0405000f + .word 230, 0x00000405 + .word DDR_TABLE_END + + .align 6 +ddr2_358_init_tab_53573: + .word 6, 0x00011705 + .word 8, 0x00000048 + .word 9, 0x000000b3 + .word 10, 0x00008f02 + .word 12, 0x00050c00 + .word 13, 0x0400050c + .word 14, 0x11160402 + .word 15, 0x02110603 + .word 17, 0x05020306 + .word 18, 0x030061a8 + .word 21, 0x06060003 + .word 23, 0x03040c01 + .word 24, 0x00000307 + .word 25, 0x002e0100 + .word 26, 0x00110ade + .word 32, 0x003200c8 + .word 47, 0x000a6300 + .word 49, 0x00400263 + .word 79, 0x02000503 + .word 80, 0x00000002 + .word 107, 0x0c0d0000 + .word 109, 0x020015bc + .word 111, 0x15bc0200 + .word 112, 0x00006cac + .word 113, 0x08120506 + .word 118, 0x02020506 + .word 229, 0x0405000f + .word 230, 0x00000405 + .word 259, 0x00000004 + .word 260, 0x0a120027 + .word 291, 0x00000004 + .word 292, 0x0a120027 + .word 323, 0x00000004 + .word 324, 0x0a120027 + .word 355, 0x00000004 + .word 356, 0x0a120027 + .word 385, 0x00000006 + .word DDR_TABLE_END + + .align 6 +ddr2_392_init_tab_53573: + .word 6, 0x0001312d + .word 8, 0x0000004f + .word 9, 0x000000c4 + .word 10, 0x00009d02 + .word 12, 0x00050c00 + .word 13, 0x0400050c + .word 14, 0x12180402 + .word 15, 0x02120603 + .word 17, 0x05020306 + .word 18, 0x03006acf + .word 21, 0x06060003 + .word 23, 0x03040c01 + .word 24, 0x00000307 + .word 25, 0x00320100 + .word 26, 0x00110be3 + .word 32, 0x003600c8 + .word 47, 0x000a6300 + .word 49, 0x00400263 + .word 79, 0x02000503 + .word 80, 0x00000002 + .word 107, 0x0c0d0000 + .word 109, 0x020017c6 + .word 111, 0x17c60200 + .word 112, 0x000076de + .word 113, 0x08120506 + .word 118, 0x02020506 + .word 229, 0x0405000f + .word 230, 0x00000405 + .word 259, 0x00000004 + .word 260, 0x0a120024 + .word 291, 0x00000004 + .word 292, 0x0a120024 + .word 323, 0x00000004 + .word 324, 0x0a120024 + .word 355, 0x00000004 + .word 356, 0x0a120024 + .word 385, 0x00000006 + .word DDR_TABLE_END + + .align 6 +ddr3_init_tab_53573: + .word 0, 0x00000600 + .word 7, 0x00000002 + .word 10, 0x00000000 + .word 11, 0x00000000 + .word 13, 0x0400060a + .word 16, 0x02040507 + .word 17, 0x0c040407 + .word 19, 0x0c040403 + .word 20, 0x03002247 + .word 27, 0x000003c7 + .word 30, 0x00000000 + .word 31, 0x00000000 + .word 33, 0x000f0200 + .word 36, 0x00000005 + .word 39, 0x20020100 + .word 49, 0x00030220 + .word 50, 0x00000008 + .word 79, 0x00000605 + .word 80, 0x00000000 + .word 107, 0x0c0d0000 + .word 116, 0x0000078e + .word 117, 0x000025c6 + .word 118, 0x02020605 + .word 134, 0x02000200 + .word 152, 0x03020101 + .word 230, 0x00000505 + .word 259, 0x00000004 + .word 291, 0x00000004 + .word 323, 0x00000004 + .word 355, 0x00000004 + .word 385, 0x00001006 + .word 386, 0x00001005 + .word DDR_TABLE_END + + .align 6 +ddr3_318_init_tab_53573: + .word 6, 0x00000004 + .word 8, 0x0000f805 + .word 9, 0x00026c0b + .word 14, 0x0c110404 + .word 15, 0x04100504 + .word 18, 0x0300570d + .word 21, 0x05050003 + .word 23, 0x03070a01 + .word 24, 0x00000205 + .word 25, 0x00230100 + .word 26, 0x000e09a4 + .word 28, 0x00030003 + .word 29, 0x000a000a + .word 32, 0x00270200 + .word 35, 0x05050500 + .word 48, 0x00000046 + .word 78, 0x04000000 + .word 109, 0x02001348 + .word 111, 0x13480200 + .word 112, 0x00006068 + .word 260, 0x0a12002d + .word 292, 0x0a12002d + .word 324, 0x0a12002d + .word 356, 0x0a12002d + .word DDR_TABLE_END + + .align 6 +ddr3_318_cl5_init_tab_53573: + .word 12, 0x00050a00 + .word 47, 0x00021000 + .word 113, 0x078e0505 + .word 229, 0x0404000f + .word DDR_TABLE_END + + .align 6 +ddr3_318_cl6_init_tab_53573: + .word 12, 0x00050c00 + .word 47, 0x00022000 + .word 113, 0x078e0506 + .word 229, 0x0405000f + .word DDR_TABLE_END + + .align 6 +ddr3_358_init_tab_53573: + .word 6, 0x00000004 + .word 8, 0x00011705 + .word 9, 0x0002b98c + .word 12, 0x00050c00 + .word 14, 0x0e130404 + .word 15, 0x04120504 + .word 18, 0x030061ef + .word 21, 0x06050003 + .word 23, 0x03070b01 + .word 24, 0x00000205 + .word 25, 0x00280100 + .word 26, 0x000e0ad9 + .word 28, 0x00030003 + .word 29, 0x000a000a + .word 32, 0x002b0200 + .word 35, 0x05050500 + .word 47, 0x00042000 + .word 48, 0x00000046 + .word 78, 0x04000000 + .word 109, 0x020015b2 + .word 111, 0x15b20200 + .word 112, 0x00006c7a + .word 113, 0x078e0506 + .word 229, 0x0405000f + .word 260, 0x0a120027 + .word 292, 0x0a120027 + .word 324, 0x0a120027 + .word 356, 0x0a120027 + .word DDR_TABLE_END + + .align 6 +ddr3_392_init_tab_53573: + .word 6, 0x00000004 + .word 8, 0x0001312d + .word 9, 0x0002faf1 + .word 12, 0x00050c00 + .word 14, 0x0f140404 + .word 15, 0x04140604 + .word 18, 0x03006b1d + .word 21, 0x06060003 + .word 23, 0x03070c01 + .word 24, 0x00000206 + .word 25, 0x002b0100 + .word 26, 0x000e0bde + .word 28, 0x00030003 + .word 29, 0x000a000a + .word 32, 0x002f0200 + .word 35, 0x05050500 + .word 47, 0x00042000 + .word 48, 0x00000046 + .word 78, 0x04000000 + .word 109, 0x020017bc + .word 111, 0x17bc0200 + .word 112, 0x000076ac + .word 113, 0x078e0506 + .word 229, 0x0405000f + .word 260, 0x0a120024 + .word 292, 0x0a120024 + .word 324, 0x0a120024 + .word 356, 0x0a120024 + .word DDR_TABLE_END + + .align 6 +ddr3_533_init_tab_53573: + .word 6, 0x00000006 + .word 8, 0x00019f8f + .word 9, 0x00040ee6 + .word 14, 0x141b0604 + .word 15, 0x041b0704 + .word 18, 0x030091dc + .word 21, 0x08070003 + .word 23, 0x03070f01 + .word 24, 0x00000207 + .word 25, 0x003b0100 + .word 26, 0x000e102c + .word 28, 0x00030004 + .word 29, 0x000a000d + .word 32, 0x00400200 + .word 35, 0x05060600 + .word 48, 0x00080046 + .word 78, 0x05000000 + .word 109, 0x02002058 + .word 111, 0x20580200 + .word 112, 0x0000a1b8 + .word 258, 0x800100a8 + .word 260, 0x0a12001b + .word 290, 0x800100a8 + .word 292, 0x0a12001b + .word 322, 0x800100a8 + .word 324, 0x0a12001b + .word 354, 0x800100a8 + .word 356, 0x0a12001b + .word DDR_TABLE_END + + .align 6 +ddr3_533_cl7_init_tab_53573: + .word 12, 0x00060e00 + .word 47, 0x00083000 + .word 113, 0x078e0607 + .word 229, 0x0506000f + .word DDR_TABLE_END + + .align 6 +ddr3_533_cl8_init_tab_53573: + .word 12, 0x00061000 + .word 47, 0x00084000 + .word 113, 0x078e0608 + .word 229, 0x0507000f + .word DDR_TABLE_END + +END(ddr_init_ca7) + +FUNC(ddr_init_regs) + mov r2,r0 + ldr r3,=DDR_TABLE_END +1: ldr r4,[r2] + cmp r4,r3 + beq 2f + ldr r5,[r2,#4] + lsl r4,r4,#2 + add r1,r9,r4 + str r5,[r1] + add r2,r2,#8 + b 1b +2: + mov pc,lr +END(ddr_init_regs) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/bcmrobo.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/bcmrobo.c new file mode 100644 index 00000000000..4765c30fb95 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/bcmrobo.c @@ -0,0 +1,3408 @@ +/* + * Broadcom 53xx RoboSwitch device driver. + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: bcmrobo.c 676803 2016-12-24 20:04:01Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef BCMFA +#include +#endif + +#ifdef BCMDBG +#define ET_ERROR(args) printf args +#else /* BCMDBG */ +#define ET_ERROR(args) +#endif /* BCMDBG */ +#define ET_MSG(args) + +#define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \ + ((len) == 2) ? *((uint16 *)(var)) : \ + *((uint32 *)(var))) + +/* + * Switch can be programmed through SPI interface, which + * has a rreg and a wreg functions to read from and write to + * registers. + */ + +/* MII access registers */ +#define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */ +#define REG_MII_CTRL 0x00 /* 53115 MII control register */ +#define REG_MII_CLAUSE_45_CTL1 0xd /* 53125 MII Clause 45 control 1 */ +#define REG_MII_CLAUSE_45_CTL2 0xe /* 53125 MII Clause 45 control 2 */ +#define REG_MII_PAGE 0x10 /* MII Page register */ +#define REG_MII_ADDR 0x11 /* MII Address register */ +#define REG_MII_DATA0 0x18 /* MII Data register 0 */ +#define REG_MII_DATA1 0x19 /* MII Data register 1 */ +#define REG_MII_DATA2 0x1a /* MII Data register 2 */ +#define REG_MII_DATA3 0x1b /* MII Data register 3 */ +#define REG_MII_AUX_STATUS2 0x1b /* Auxiliary status 2 register */ +#define REG_MII_AUTO_PWRDOWN 0x1c /* 53115 Auto power down register */ +#define REG_MII_BRCM_TEST 0x1f /* Broadcom test register */ + +/* Page numbers */ +#define PAGE_CTRL 0x00 /* Control page */ +#define PAGE_STATUS 0x01 /* Status page */ +#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */ +#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */ +#define PAGE_FC 0x0a /* Flow control register page */ +#define PAGE_GPHY_MII_P0 0x10 /* Port0 Internal GPHY MII registers page */ +#define PAGE_GPHY_MII_P4 0x14 /* Last/Port4 Internal GPHY MII registers page */ +#define PAGE_MIB_P0 0x20 /* Port0 MIB page */ +#define PAGE_MIB_P1 0x21 /* Port1 MIB page */ +#define PAGE_MIB_P2 0x22 /* Port2 MIB page */ +#define PAGE_MIB_P3 0x23 /* Port3 MIB page */ +#define PAGE_MIB_P4 0x24 /* Port4 MIB page */ +#define PAGE_MIB_P5 0x25 /* Port5 MIB page */ +#define PAGE_MIB_P6 0x26 /* Port6 MIB page */ +#define PAGE_MIB_P7 0x27 /* Port7 MIB page */ +#define PAGE_MIB_P8 0x28 /* Port8 (IMP) MIB page */ +#define PAGE_VLAN 0x34 /* VLAN page */ +#define PAGE_CFPTCAM 0xa0 /* CFP TCAM registers page */ +#define PAGE_CFP 0xa1 /* CFP configuration registers page */ + +/* Control page registers */ +#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */ +#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */ +#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */ +#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */ +#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */ +#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */ +#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */ +#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */ +#define REG_CTRL_IMP 0x08 /* IMP port traffic control register */ +#define REG_CTRL_MODE 0x0B /* Switch Mode register */ +#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */ +#define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */ +#define REG_CTRL_RSV_MCAST_CTRL 0x2f /* Reserved Multicast Register */ +#define REG_CTRL_SRST 0x79 /* Software reset control register */ + +/* Management/Mirroring Registers */ +#define REG_MMR_ATCR 0x06 /* Aging Time Control register */ +#define REG_MMR_MCCR 0x10 /* Mirror Capture Control register */ +#define REG_MMR_IMCR 0x12 /* Ingress Mirror Control register */ +#define REG_MMR_IMMAC 0x16 /* Ingress Mirror MAC address register */ + +/* Management Page registers */ +#define REG_MGMT_CFG 0x00 +#define REG_IMP0_PORT 0x01 +#define REG_IMP1_PORT 0x02 +#define REG_BRCM_HDR 0x03 + +/* Status Page Registers */ +#define REG_STATUS_LINK 0x00 /* Link Status Summary */ +#define REG_STATUS_REV 0x50 /* Revision Register */ + +#define REG_DEVICE_ID 0x30 /* 539x Device id: */ + +/* Internal GPHY MII registers */ +#define REG_GPHY_MII_CTL 0x0 /* MII Control register */ +#define REG_GPHY_DSP 0x2a /* DSP Coefficient Read/Write Port register */ +#define REG_GPHY_DSPA 0x2e /* DSP Coefficient Address register */ +#define REG_GPHY_AUXCTL 0x30 /* Auxiliary Control register */ + +/* VLAN page registers */ +#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */ +#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */ +#define REG_VLAN_CTRL2 0x02 /* VLAN Control 2 register */ +#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */ +#define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */ +#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */ +#define REG_VLAN_WRITE 0x08 /* VLAN Write register */ +#define REG_VLAN_READ 0x0C /* VLAN Read register */ +#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */ +#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */ +#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */ +#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */ +#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */ +#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */ +#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */ +#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */ +#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */ +#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */ + +#define VLAN_NUMVLANS 16 /* # of VLANs */ + +/* ARL/VLAN Table Access page registers */ +#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */ +#define REG_VTBL_MINDX 0x02 /* MAC Address Index */ +#define REG_VTBL_VINDX 0x08 /* VID Table Index */ +#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */ +#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */ +#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */ +#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */ +#define REG_VTBL_SADDR 0x22 /* ARL Search Address */ +#define REG_VTBL_SRES 0x24 /* ARL Search Result */ +#define REG_VTBL_SREXT 0x2c /* ARL Search Result */ +#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */ +#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */ +#define REG_VTBL_PREG 0xFF /* Page Register */ +#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */ +#define REG_VTBL_INDX 0x61 /* VLAN table address index register */ +#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */ +#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */ +#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */ +#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */ + +#define REG_FC_OOBPAUSE 0xe0 /* OOB Pause Signal enable register */ + +/* Port MIB registers */ +#define REG_MIB_TXDROPPKTS 0x08 /* MIB TxDropPkts register */ +#define REG_MIB_TXQ0PKT 0x0C /* MIB TxQ0Pkt register */ +#define REG_MIB_TXBCPKTS 0x10 /* MIB TxBroadcastPkts register */ +#define REG_MIB_TXMCPKTS 0x14 /* MIB TxMulticastPkts register */ +#define REG_MIB_TXUCPKTS 0x18 /* MIB TxUnicastPkts register */ +#define REG_MIB_TXDISCARD 0x34 /* MIB TxDiscard register */ +#define REG_MIB_TXPAUSEPKTS 0x38 /* MIB TxPausetPkts register */ +#define REG_MIB_RXUNDERSZPKTS 0x58 /* MIB RxUndersizePkts register */ +#define REG_MIB_RXPAUSEPKTS 0x5C /* MIB RxPausetPkts register */ +#define REG_MIB_RXOVERSZPKTS 0x78 /* MIB RxOversizePkts register */ +#define REG_MIB_RXJABBERS 0x7C /* MIB RxJabbers register */ +#define REG_MIB_RXALIGNERROR 0x80 /* MIB RxAlignmentErrors register */ +#define REG_MIB_RXFCSERROR 0x84 /* MIB RxFCSErrors register */ +#define REG_MIB_RXDROPPKTS 0x90 /* MIB RxDropPkts register */ +#define REG_MIB_RXUCPKTS 0x94 /* MIB RxUnicastPkts register */ +#define REG_MIB_RXMCPKTS 0x98 /* MIB RxMulticastPkts register */ +#define REG_MIB_RXBCPKTS 0x9C /* MIB RxBroadcastPkts register */ +#define REG_MIB_RXFRAGMENTS 0xA4 /* MIB RxFragments register */ +#define REG_MIB_RXDISCARD 0xC0 /* MIB RxDiscard register */ + +#define REG_MIB_5325E_MODESEL 0x04 /* MIB Mode Select Register */ +#define REG_MIB_5325E_TXGOODPKTS 0x00 /* MIB TxGoodPkts register */ +#define REG_MIB_5325E_TXUCPKTS 0x02 /* MIB TxUnicastPkts register */ +#define REG_MIB_5325E_RXGOODPKTS 0x04 /* MIB RxGoodPkts register */ +#define REG_MIB_5325E_RXUCPKTS 0x06 /* MIB RxUnicastPkts register */ +#define REG_MIB_5325E_TXCOLBYTES 0x00 /* MIB TxCollisionBytes register */ +#define REG_MIB_5325E_TXOCTETBYTES 0x02 /* MIB TxOctetsBytes register */ +#define REG_MIB_5325E_RXFCSERRPKTS 0x04 /* MIB RxFCSErrorsPkts register */ +#define REG_MIB_5325E_RXGOODOCTETS 0x06 /* MIB RxGoodOctetsBytes register */ + +/* CFP TCAM page registers */ +#define REG_CFPTCAM_ACC 0x00 /* CFP access register */ +#define REG_CFPTCAM_DATA0 0x10 /* CFP TCAM Data 0 register */ +#define REG_CFPTCAM_DATA1 0x14 /* CFP TCAM Data 1 register */ +#define REG_CFPTCAM_DATA2 0x18 /* CFP TCAM Data 2 register */ +#define REG_CFPTCAM_DATA3 0x1c /* CFP TCAM Data 3 register */ +#define REG_CFPTCAM_DATA4 0x20 /* CFP TCAM Data 4 register */ +#define REG_CFPTCAM_DATA5 0x24 /* CFP TCAM Data 5 register */ +#define REG_CFPTCAM_DATA6 0x28 /* CFP TCAM Data 6 register */ +#define REG_CFPTCAM_DATA7 0x2c /* CFP TCAM Data 7 register */ +#define REG_CFPTCAM_MASK0 0x30 /* CFP TCAM Mask 0 register */ +#define REG_CFPTCAM_MASK1 0x34 /* CFP TCAM Mask 1 register */ +#define REG_CFPTCAM_MASK2 0x38 /* CFP TCAM Mask 2 register */ +#define REG_CFPTCAM_MASK3 0x3c /* CFP TCAM Mask 3 register */ +#define REG_CFPTCAM_MASK4 0x40 /* CFP TCAM Mask 4 register */ +#define REG_CFPTCAM_MASK5 0x44 /* CFP TCAM Mask 5 register */ +#define REG_CFPTCAM_MASK6 0x48 /* CFP TCAM Mask 6 register */ +#define REG_CFPTCAM_MASK7 0x4c /* CFP TCAM Mask 7 register */ +#define REG_CFPTCAM_ACT_POL_DATA0 0x50 /* CFP CFP Action/Policy Data 0 Register */ +#define REG_CFPTCAM_ACT_POL_DATA1 0x54 /* CFP CFP Action/Policy Data 1 Register */ +#define REG_CFPTCAM_RATE_METER0 0x60 /* CFP CFP RATE METER DATA 0 Register */ +#define REG_CFPTCAM_RATE_METER1 0x64 /* CFP CFP RATE METER DATA 0 Register */ +#define REG_CFPTCAM_RATE_INBAND 0x70 /* CFP CFP RATE In-Band Statistic Register */ +#define REG_CFPTCAM_RATE_OUTBAND 0x74 /* CFP CFP RATE In-Band Statistic Register */ + +#define CFP_ACC_RD_STS_SHIFT 28 +#define CFP_ACC_XCESS_ADDR_SHIFT 16 +#define CFP_ACC_RAM_SEL_SHIFT 10 +#define CFP_ACC_OP_SEL_SHIFT 1 +#define CFP_ACC_OP_STR_DONE 1 +#define CFP_ACT_POL_DATA0_CFMI_SHIFT 24 /* CHANGE_FWRD_MAP_IB Shift */ +#define CFP_ACT_POL_DATA0_DMI_SHIFT 14 /* DST_MAP_IB Shift */ +#define CFP_ACT_POL_DATA1_CFMO_SHIFT 11 /* CHANGE_FWRD_MAP_OB Shift */ +#define CFP_ACT_POL_DATA1_DMO_SHIFT 1 /* DST_MAP_OB Shift */ + +/* CFP Configuration page registers */ +#define REG_CFP_CTL_REG 0x00 /* CFP Control Register */ +#define REG_CFP_UDF_0_A_0_8 0x10 /* UDFs of slice 0 for IPv4 packet Register */ +#define REG_CFP_UDF_1_A_0_8 0x20 /* UDFs of slice 1 for IPv4 packet Register */ +#define REG_CFP_UDF_2_A_0_8 0x30 /* UDFs of slice 2 for IPv4 packet Register */ +#define REG_CFP_UDF_0_B_0_8 0x40 /* UDFs of slice 0 for IPv6 packet Register */ +#define REG_CFP_UDF_1_B_0_8 0x50 /* UDFs of slice 1 for IPv6 packet Register */ +#define REG_CFP_UDF_2_B_0_8 0x60 /* UDFs of slice 2 for IPv6 packet Register */ +#define REG_CFP_UDF_0_C_0_8 0x70 /* UDFs of slice 0 for none-IP Register */ +#define REG_CFP_UDF_1_C_0_8 0x80 /* UDFs of slice 0 for none-IP Register */ +#define REG_CFP_UDF_2_C_0_8 0x90 /* UDFs of slice 0 for none-IP Register */ +#define REG_CFP_UDF_0_D_0_11 0xa0 /* UDFs for IPv6 Chain Rule Register */ + +#define CFP_ACC_RD_STS_WAIT(robo, mask) \ +do { \ + uint32 val32 = 0; \ + (robo)->ops->read_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACC, &val32, sizeof(val32)); \ + if ((val32 >> CFP_ACC_RD_STS_SHIFT) & (mask)) \ + break; \ + bcm_mdelay(1); \ +} while (1) + +/* a flag to control Manage Mode enable/disable */ +static bool mang_mode_en = FALSE; + +#define RXTX_FLOW_CTRL_MASK 0x3 /* 53125 flow control capability mask */ +#define RXTX_FLOW_CTRL_SHIFT 4 /* 53125 flow contorl capability offset */ + +#ifndef _CFE_ +/* SPI registers */ +#define REG_SPI_PAGE 0xff /* SPI Page register */ + +/* Access switch registers through GPIO/SPI */ + +/* Minimum timing constants */ +#define SCK_EDGE_TIME 2 /* clock edge duration - 2us */ +#define MOSI_SETUP_TIME 1 /* input setup duration - 1us */ +#define SS_SETUP_TIME 1 /* select setup duration - 1us */ + +/* misc. constants */ +#define SPI_MAX_RETRY 100 + +/* Enable GPIO access to the chip */ +static void +gpio_enable(robo_info_t *robo) +{ + /* Enable GPIO outputs with SCK and MOSI low, SS high */ + si_gpioout(robo->sih, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY); + si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, + robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY); +} + +/* Disable GPIO access to the chip */ +static void +gpio_disable(robo_info_t *robo) +{ + /* Disable GPIO outputs with all their current values */ + si_gpioouten(robo->sih, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY); +} + +/* Write a byte stream to the chip thru SPI */ +static int +spi_write(robo_info_t *robo, uint8 *buf, uint len) +{ + uint i; + uint8 mask; + + /* Byte bang from LSB to MSB */ + for (i = 0; i < len; i++) { + /* Bit bang from MSB to LSB */ + for (mask = 0x80; mask; mask >>= 1) { + /* Clock low */ + si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY); + OSL_DELAY(SCK_EDGE_TIME); + + /* Sample on rising edge */ + if (mask & buf[i]) + si_gpioout(robo->sih, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY); + else + si_gpioout(robo->sih, robo->mosi, 0, GPIO_DRV_PRIORITY); + OSL_DELAY(MOSI_SETUP_TIME); + + /* Clock high */ + si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY); + OSL_DELAY(SCK_EDGE_TIME); + } + } + + return 0; +} + +/* Read a byte stream from the chip thru SPI */ +static int +spi_read(robo_info_t *robo, uint8 *buf, uint len) +{ + uint i, timeout; + uint8 rack, mask, byte; + + /* Timeout after 100 tries without RACK */ + for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) { + /* Bit bang from MSB to LSB */ + for (mask = 0x80, byte = 0; mask; mask >>= 1) { + /* Clock low */ + si_gpioout(robo->sih, robo->sck, 0, GPIO_DRV_PRIORITY); + OSL_DELAY(SCK_EDGE_TIME); + + /* Sample on falling edge */ + if (si_gpioin(robo->sih) & robo->miso) + byte |= mask; + + /* Clock high */ + si_gpioout(robo->sih, robo->sck, robo->sck, GPIO_DRV_PRIORITY); + OSL_DELAY(SCK_EDGE_TIME); + } + /* RACK when bit 0 is high */ + if (!rack) { + rack = (byte & 1); + timeout--; + continue; + } + /* Byte bang from LSB to MSB */ + buf[i] = byte; + i++; + } + + if (timeout == 0) { + ET_ERROR(("spi_read: timeout")); + return -1; + } + + return 0; +} + +/* Enable/disable SPI access */ +static void +spi_select(robo_info_t *robo, uint8 spi) +{ + if (spi) { + /* Enable SPI access */ + si_gpioout(robo->sih, robo->ss, 0, GPIO_DRV_PRIORITY); + } else { + /* Disable SPI access */ + si_gpioout(robo->sih, robo->ss, robo->ss, GPIO_DRV_PRIORITY); + } + OSL_DELAY(SS_SETUP_TIME); +} + +/* Select chip and page */ +static void +spi_goto(robo_info_t *robo, uint8 page) +{ + uint8 reg8 = REG_SPI_PAGE; /* page select register */ + uint8 cmd8; + + /* Issue the command only when we are on a different page */ + if (robo->page == page) + return; + + robo->page = page; + + /* Enable SPI access */ + spi_select(robo, 1); + + /* Select new page with CID 0 */ + cmd8 = ((6 << 4) | /* normal SPI */ + 1); /* write */ + spi_write(robo, &cmd8, 1); + spi_write(robo, ®8, 1); + spi_write(robo, &page, 1); + + /* Disable SPI access */ + spi_select(robo, 0); +} + +/* Write register thru SPI */ +static int +spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len) +{ + int status = 0; + uint8 cmd8; + union { + uint8 val8; + uint16 val16; + uint32 val32; + } bytes; + + if ((len != 1) && (len != 2) && (len != 4)) { + printf("Invalid length. For SPI mode, the length can only be 1, 2, and 4 bytes.\n"); + return -1; + } + + /* validate value length and buffer address */ + ASSERT(len == 1 || (len == 2 && !((int)val & 1)) || + (len == 4 && !((int)val & 3))); + + /* Select chip and page */ + spi_goto(robo, page); + + /* Enable SPI access */ + spi_select(robo, 1); + + /* Write with CID 0 */ + cmd8 = ((6 << 4) | /* normal SPI */ + 1); /* write */ + spi_write(robo, &cmd8, 1); + spi_write(robo, &addr, 1); + switch (len) { + case 1: + bytes.val8 = *(uint8 *)val; + break; + case 2: + bytes.val16 = htol16(*(uint16 *)val); + break; + case 4: + bytes.val32 = htol32(*(uint32 *)val); + break; + } + spi_write(robo, (uint8 *)val, len); + + ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr, + *(uint16 *)val, len)); + /* Disable SPI access */ + spi_select(robo, 0); + return status; +} + +/* Read register thru SPI in fast SPI mode */ +static int +spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len) +{ + int status = 0; + uint8 cmd8; + union { + uint8 val8; + uint16 val16; + uint32 val32; + } bytes; + + if ((len != 1) && (len != 2) && (len != 4)) { + printf("Invalid length. For SPI mode, the length can only be 1, 2, and 4 bytes.\n"); + return -1; + } + + /* validate value length and buffer address */ + ASSERT(len == 1 || (len == 2 && !((int)val & 1)) || + (len == 4 && !((int)val & 3))); + + /* Select chip and page */ + spi_goto(robo, page); + + /* Enable SPI access */ + spi_select(robo, 1); + + /* Fast SPI read with CID 0 and byte offset 0 */ + cmd8 = (1 << 4); /* fast SPI */ + spi_write(robo, &cmd8, 1); + spi_write(robo, &addr, 1); + status = spi_read(robo, (uint8 *)&bytes, len); + switch (len) { + case 1: + *(uint8 *)val = bytes.val8; + break; + case 2: + *(uint16 *)val = ltoh16(bytes.val16); + break; + case 4: + *(uint32 *)val = ltoh32(bytes.val32); + break; + } + + ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr, + *(uint16 *)val, len)); + + /* Disable SPI access */ + spi_select(robo, 0); + return status; +} + +/* SPI/gpio interface functions */ +static dev_ops_t spigpio = { + gpio_enable, + gpio_disable, + spi_wreg, + spi_rreg, + "SPI (GPIO)" +}; +#endif /* _CFE_ */ + +/* Access switch registers through MII (MDC/MDIO) */ + +#define MII_MAX_RETRY 100 + +/* Write register thru MDC/MDIO */ +static int +mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) +{ + uint16 cmd16, val16; + void *h = robo->h; + int i; + uint8 *ptr = (uint8 *)val; + + /* do not allow access to internal PHY MII registers */ + if ((page >= PAGE_GPHY_MII_P0) && (page <= PAGE_GPHY_MII_P4)) { + ET_ERROR(("mii_wreg: cannot access MII registers through pseudo phy interface\n")); + return -1; + } + + /* validate value length and buffer address */ + ASSERT(len == 1 || len == 6 || len == 8 || + ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); + + ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg, + VARG(val, len), len)); + + /* set page number - MII register 0x10 */ + if (robo->page != page) { + cmd16 = ((page << 8) | /* page number */ + 1); /* mdc/mdio access enable */ + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16); + robo->page = page; + } + + switch (len) { + case 8: + val16 = ptr[7]; + val16 = ((val16 << 8) | ptr[6]); + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16); + /* FALLTHRU */ + + case 6: + val16 = ptr[5]; + val16 = ((val16 << 8) | ptr[4]); + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16); + val16 = ptr[3]; + val16 = ((val16 << 8) | ptr[2]); + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16); + val16 = ptr[1]; + val16 = ((val16 << 8) | ptr[0]); + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); + break; + + case 4: + val16 = (uint16)((*(uint32 *)val) >> 16); + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16); + val16 = (uint16)(*(uint32 *)val); + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); + break; + + case 2: + val16 = *(uint16 *)val; + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); + break; + + case 1: + val16 = *(uint8 *)val; + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16); + break; + } + + /* set register address - MII register 0x11 */ + cmd16 = ((reg << 8) | /* register address */ + 1); /* opcode write */ + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16); + + /* is operation finished? */ + for (i = MII_MAX_RETRY; i > 0; i --) { + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR); + if ((val16 & 3) == 0) + break; + } + + /* timed out */ + if (!i) { + ET_ERROR(("mii_wreg: timeout")); + return -1; + } + return 0; +} + +/* Read register thru MDC/MDIO */ +static int +mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) +{ + uint16 cmd16, val16; + void *h = robo->h; + int i; + uint8 *ptr = (uint8 *)val; + + /* do not allow access to internal PHY MII registers */ + if ((page >= PAGE_GPHY_MII_P0) && (page <= PAGE_GPHY_MII_P4)) { + ET_ERROR(("mii_rreg: cannot access MII registers through pseudo phy interface\n")); + return -1; + } + + /* validate value length and buffer address */ + ASSERT(len == 1 || len == 6 || len == 8 || + ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); + + /* set page number - MII register 0x10 */ + if (robo->page != page) { + cmd16 = ((page << 8) | /* page number */ + 1); /* mdc/mdio access enable */ + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16); + robo->page = page; + } + + /* set register address - MII register 0x11 */ + cmd16 = ((reg << 8) | /* register address */ + 2); /* opcode read */ + robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16); + + /* is operation finished? */ + for (i = MII_MAX_RETRY; i > 0; i --) { + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR); + if ((val16 & 3) == 0) + break; + } + /* timed out */ + if (!i) { + ET_ERROR(("mii_rreg: timeout")); + return -1; + } + + switch (len) { + case 8: + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3); + ptr[7] = (val16 >> 8); + ptr[6] = (val16 & 0xff); + /* FALLTHRU */ + + case 6: + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2); + ptr[5] = (val16 >> 8); + ptr[4] = (val16 & 0xff); + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1); + ptr[3] = (val16 >> 8); + ptr[2] = (val16 & 0xff); + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); + ptr[1] = (val16 >> 8); + ptr[0] = (val16 & 0xff); + break; + + case 4: + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1); + *(uint32 *)val = (((uint32)val16) << 16); + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); + *(uint32 *)val |= val16; + break; + + case 2: + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); + *(uint16 *)val = val16; + break; + + case 1: + val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0); + *(uint8 *)val = (uint8)(val16 & 0xff); + break; + } + + ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, + VARG(val, len), len)); + + return 0; +} + +/* MII interface functions */ +static dev_ops_t mdcmdio = { + NULL, + NULL, + mii_wreg, + mii_rreg, + "MII (MDC/MDIO)" +}; + +/* + * BCM4707, 4708 and 4709 use ChipcommonB Switch Register Access Bridge Registers (SRAB) + * to access the switch registers + */ + +#ifdef ROBO_SRAB +#define SRAB_ENAB(sih) ((sih)->ccrev == 42) +#define NS_CHIPCB_SRAB 0x18007000 /* NorthStar Chip Common B SRAB base */ +#define SET_ROBO_SRABREGS(robo) ((robo)->srabregs = \ + (srabregs_t *)REG_MAP(NS_CHIPCB_SRAB, SI_CORE_SIZE)) +#define SET_ROBO_SRABOPS(robo) ((robo)->ops = &srab) +#else +#define SRAB_ENAB(sih) (0) +#define SET_ROBO_SRABREGS(robo) +#define SET_ROBO_SRABOPS(robo) +#endif /* ROBO_SRAB */ + +#ifdef ROBO_SRAB +#define SRAB_MAX_RETRY 1000 +static int +srab_request_grant(robo_info_t *robo) +{ + int i, ret = 0; + uint32 val32; + + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); + val32 |= CFG_F_rcareq_MASK; + W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); + + /* Wait for command complete */ + for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); + if ((val32 & CFG_F_rcagnt_MASK)) + break; + } + + /* timed out */ + if (!i) { + ET_ERROR(("srab_request_grant: timeout")); + ret = -1; + } + + return ret; +} + +static void +srab_release_grant(robo_info_t *robo) +{ + uint32 val32; + + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); + val32 &= ~CFG_F_rcareq_MASK; + W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); +} + +static int +srab_interface_reset(robo_info_t *robo) +{ + int i, ret = 0; + uint32 val32; + + /* Wait for switch initialization complete */ + for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); + if ((val32 & CFG_F_sw_init_done_MASK)) + break; + } + + /* timed out */ + if (!i) { + ET_ERROR(("srab_interface_reset: timeout sw_init_done")); + ret = -1; + } + + /* Set the SRAU reset bit */ + W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, CFG_F_sra_rst_MASK); + + /* Wait for it to auto-clear */ + for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); + if ((val32 & CFG_F_sra_rst_MASK) == 0) + break; + } + + /* timed out */ + if (!i) { + ET_ERROR(("srab_interface_reset: timeout sra_rst")); + ret |= -2; + } + + return ret; +} + +static int +srab_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) +{ + uint16 val16; + uint32 val32; + uint32 val_h = 0, val_l = 0; + int i, ret = 0; + uint8 *ptr = (uint8 *)val; + + /* validate value length and buffer address */ + ASSERT(len == 1 || len == 6 || len == 8 || + ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); + + ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg, + VARG(val, len), len)); + + srab_request_grant(robo); + + /* Load the value to write */ + switch (len) { + case 8: + val16 = ptr[7]; + val16 = ((val16 << 8) | ptr[6]); + val_h = val16 << 16; + /* FALLTHRU */ + + case 6: + val16 = ptr[5]; + val16 = ((val16 << 8) | ptr[4]); + val_h |= val16; + + val16 = ptr[3]; + val16 = ((val16 << 8) | ptr[2]); + val_l = val16 << 16; + val16 = ptr[1]; + val16 = ((val16 << 8) | ptr[0]); + val_l |= val16; + break; + + case 4: + val_l = *(uint32 *)val; + break; + + case 2: + val_l = *(uint16 *)val; + break; + + case 1: + val_l = *(uint8 *)val; + break; + } + W_REG(si_osh(robo->sih), &robo->srabregs->wd_h, val_h); + W_REG(si_osh(robo->sih), &robo->srabregs->wd_l, val_l); + + /* We don't need this variable */ + if (robo->page != page) + robo->page = page; + + /* Issue the write command */ + val32 = ((page << CFG_F_sra_page_R) + | (reg << CFG_F_sra_offset_R) + | CFG_F_sra_gordyn_MASK + | CFG_F_sra_write_MASK); + W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); + + /* Wait for command complete */ + for (i = SRAB_MAX_RETRY; i > 0; i --) { + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); + if ((val32 & CFG_F_sra_gordyn_MASK) == 0) + break; + } + + /* timed out */ + if (!i) { + ET_ERROR(("srab_wreg: timeout")); + srab_interface_reset(robo); + ret = -1; + } + + srab_release_grant(robo); + + return ret; +} + +static int +srab_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) +{ + uint32 val32; + uint32 val_h = 0, val_l = 0; + int i, ret = 0; + uint8 *ptr = (uint8 *)val; + + /* validate value length and buffer address */ + ASSERT(len == 1 || len == 6 || len == 8 || + ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); + + srab_request_grant(robo); + + /* We don't need this variable */ + if (robo->page != page) + robo->page = page; + + /* Assemble read command */ + srab_request_grant(robo); + + val32 = ((page << CFG_F_sra_page_R) + | (reg << CFG_F_sra_offset_R) + | CFG_F_sra_gordyn_MASK); + W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); + + /* is operation finished? */ + for (i = SRAB_MAX_RETRY; i > 0; i --) { + val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); + if ((val32 & CFG_F_sra_gordyn_MASK) == 0) + break; + } + + /* timed out */ + if (!i) { + ET_ERROR(("srab_read: timeout")); + srab_interface_reset(robo); + ret = -1; + goto err; + } + + /* Didn't time out, read and return the value */ + val_h = R_REG(si_osh(robo->sih), &robo->srabregs->rd_h); + val_l = R_REG(si_osh(robo->sih), &robo->srabregs->rd_l); + + switch (len) { + case 8: + ptr[7] = (val_h >> 24); + ptr[6] = ((val_h >> 16) & 0xff); + /* FALLTHRU */ + + case 6: + ptr[5] = ((val_h >> 8) & 0xff); + ptr[4] = (val_h & 0xff); + ptr[3] = (val_l >> 24); + ptr[2] = ((val_l >> 16) & 0xff); + ptr[1] = ((val_l >> 8) & 0xff); + ptr[0] = (val_l & 0xff); + break; + + case 4: + *(uint32 *)val = val_l; + break; + + case 2: + *(uint16 *)val = (uint16)(val_l & 0xffff); + break; + + case 1: + *(uint8 *)val = (uint8)(val_l & 0xff); + break; + } + + ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, + VARG(val, len), len)); + +err: + srab_release_grant(robo); + + return ret; +} + +/* SRAB interface functions */ +static dev_ops_t srab = { + NULL, + NULL, + srab_wreg, + srab_rreg, + "SRAB" +}; +#else +#define srab_interface_reset(a) do {} while (0) +#define srab_rreg(a, b, c, d, e) 0 +#endif /* ROBO_SRAB */ + +static void +bcm_robo_gphy_misc_wreg(robo_info_t *robo, int port, uint8 reg, uint8 ch, uint16 val16) +{ + uint16 addr; + + ASSERT(ROBO_IS_BCM5301X(robo->devid)); + + addr = (ch << 13) | /* channel selection */ + (0 << 8) | /* DSP filter 0 for misc registers */ + reg; + robo->ops->write_reg(robo, (PAGE_GPHY_MII_P0 + port), REG_GPHY_DSPA, + &addr, sizeof(addr)); + + robo->ops->write_reg(robo, (PAGE_GPHY_MII_P0 + port), REG_GPHY_DSP, + &val16, sizeof(val16)); +} + +/* Need to apply the setting for EGPHY40 */ +static void +bcm_robo_gphy_config(robo_info_t *robo, int port) +{ + uint16 val16; + int retry = 10; + + if (!ROBO_IS_BCM5301X(robo->devid)) + return; + + /* wait for out of phy reset state */ + while (retry--) { + robo->ops->read_reg(robo, (PAGE_GPHY_MII_P0 + port), + REG_GPHY_MII_CTL, &val16, sizeof(val16)); + /* check phy reset bit */ + if (!(val16 & (1 << 15))) + break; + bcm_mdelay(100); + } + + if (val16 & (1 << 15)) { + ET_ERROR(("%s: failed to leave phy reset state\n", __FUNCTION__)); + return; + } + + /* CORE_SHD18_000: AUX control register, enable DSP clk */ + val16 = 0x0C00; + robo->ops->write_reg(robo, (PAGE_GPHY_MII_P0 + port), REG_GPHY_AUXCTL, + &val16, sizeof(val16)); + + /* AFE registers start from DSP TAP30h */ + /* AFE_RXCONFIG_0 */ + bcm_robo_gphy_misc_wreg(robo, port, 0x30, 0, 0xD771); + + /* AFE_RXCONFIG_2 */ + bcm_robo_gphy_misc_wreg(robo, port, 0x30, 2, 0x1872); + + /* AFE_HPF_TRIM */ + bcm_robo_gphy_misc_wreg(robo, port, 0x33, 3, 0x0006); + + /* AFE_PLLCTRL_4 */ + bcm_robo_gphy_misc_wreg(robo, port, 0x33, 0, 0x0500); + + /* DSP_TAP10 */ + bcm_robo_gphy_misc_wreg(robo, port, 0xA, 0, 0x011B); + + /* re-AutoNeg */ + robo->ops->read_reg(robo, (PAGE_GPHY_MII_P0 + port), + REG_GPHY_MII_CTL, &val16, sizeof(val16)); + val16 |= 0x0240; + val16 &= 0xDFFF; + robo->ops->write_reg(robo, (PAGE_GPHY_MII_P0 + port), + REG_GPHY_MII_CTL, &val16, sizeof(val16)); + + ET_ERROR(("%s: gphy config done for port %d\n", __FUNCTION__, port)); +} + +/* Need to config bcm5301x GPHY after doing PHY reset */ +void +bcm_robo_check_gphy_reset(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) +{ + uint16 val16; + + if (!ROBO_IS_BCM5301X(robo->devid)) + return; + + if (len != 2) + return; + + /* return if not accessing internal GPHY registers */ + if (!(page >= PAGE_GPHY_MII_P0) || !(page < (PAGE_GPHY_MII_P0 + MAX_NO_PHYS))) + return; + + /* check reset bit */ + val16 = *(uint16 *)val; + if ((reg == REG_GPHY_MII_CTL) && (val16 & (1 << 15))) { + bcm_robo_gphy_config(robo, (page - PAGE_GPHY_MII_P0)); + } +} + +/* High level switch configuration functions. */ + +/* Get access to the RoboSwitch */ +robo_info_t * +bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr) +{ + robo_info_t *robo; + uint32 reset, idx; +#ifndef _CFE_ + const char *et1port, *et1phyaddr; + int mdcport = 0, phyaddr = 0; +#endif /* _CFE_ */ + int lan_portenable = 0; + int rc; + + /* Allocate and init private state */ + if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) { + ET_ERROR(("robo_attach: out of memory, malloced %d bytes", + MALLOCED(si_osh(sih)))); + return NULL; + } + bzero(robo, sizeof(robo_info_t)); + + robo->h = h; + robo->sih = sih; + robo->vars = vars; + robo->miird = miird; + robo->miiwr = miiwr; + robo->page = -1; + + if (SRAB_ENAB(sih) && BCM4707_CHIP(sih->chip)) { + SET_ROBO_SRABREGS(robo); + } + + /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when + * romboot CFE loads linux over WAN port and Linux enables LAN ports later + */ + if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) != + GPIO_PIN_NOTDEFINED) { + lan_portenable = 1 << lan_portenable; + si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); + si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); + bcm_mdelay(5); + } + + /* Trigger external reset by nvram variable existance */ + if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) != + GPIO_PIN_NOTDEFINED) { + /* + * Reset sequence: RESET low(50ms)->high(20ms) + * + * We have to perform a full sequence for we don't know how long + * it has been from power on till now. + */ + ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset)); + reset = 1 << reset; + + /* Keep RESET low for 50 ms */ + si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY); + si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY); + bcm_mdelay(50); + + /* Keep RESET high for at least 20 ms */ + si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY); + bcm_mdelay(20); + } else { + /* In case we need it */ + idx = si_coreidx(sih); + + if (si_setcore(sih, ROBO_CORE_ID, 0)) { + /* If we have an internal robo core, reset it using si_core_reset */ + ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__)); + si_core_reset(sih, 0, 0); + robo->corerev = si_corerev(sih); + } + else if (SRAB_ENAB(sih) && BCM4707_CHIP(sih->chip)) { + srab_interface_reset(robo); + rc = srab_rreg(robo, PAGE_MMR, REG_VERSION_ID, &robo->corerev, 1); + } + else { + mii_rreg(robo, PAGE_STATUS, REG_STATUS_REV, &robo->corerev, 1); + } + si_setcoreidx(sih, idx); + ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev)); + } + + if (SRAB_ENAB(sih) && BCM4707_CHIP(sih->chip)) { + rc = srab_rreg(robo, PAGE_MMR, REG_DEVICE_ID, &robo->devid, sizeof(uint32)); + + ET_MSG(("%s: devid read %ssuccesfully via srab: 0x%x\n", + __FUNCTION__, rc ? "un" : "", robo->devid)); + + SET_ROBO_SRABOPS(robo); + if ((rc != 0) || (robo->devid == 0)) { + ET_ERROR(("%s: error reading devid\n", __FUNCTION__)); + MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); + return NULL; + } + ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid)); + } + else if (miird && miiwr) { + uint16 tmp; + int retry_count = 0; + + /* Read the PHY ID */ + tmp = miird(h, PSEUDO_PHYAD, 2); + + /* WAR: Enable mdc/mdio access to the switch registers. Unless + * a write to bit 0 of pseudo phy register 16 is done we are + * unable to talk to the switch on a customer ref design. + */ + if (tmp == 0xffff) { + miiwr(h, PSEUDO_PHYAD, 16, 1); + tmp = miird(h, PSEUDO_PHYAD, 2); + } + + if (tmp != 0xffff) { + /* + * XXX Reading the register multiple times does return correct + * device id all the time on 539x !? + */ + do { + rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, + &robo->devid, sizeof(uint16)); + if (rc != 0) + break; + retry_count++; + } while ((robo->devid == 0) && (retry_count < 10)); + + ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", + __FUNCTION__, rc ? "un" : "", robo->devid)); + ET_MSG(("%s: mii access to switch works\n", __FUNCTION__)); + robo->ops = &mdcmdio; + if ((rc != 0) || (robo->devid == 0)) { + ET_MSG(("%s: error reading devid, assuming 5325e\n", + __FUNCTION__)); + robo->devid = DEVID5325; + } + } + ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid)); + } + + if ((robo->devid == DEVID5395) || + (robo->devid == DEVID5397) || + (robo->devid == DEVID5398)) { + uint8 srst_ctrl; + + /* If it is a 539x switch, use the soft reset register */ + ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__)); + + /* Reset the 539x switch core and register file */ + srst_ctrl = 0x83; + mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8)); + srst_ctrl = 0x00; + mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8)); + } + + if (ROBO_IS_BCM5301X(robo->devid)) { + int port; + + for (port = 0; port < MAX_NO_PHYS; port++) { + bcm_robo_gphy_config(robo, port); + } + ET_MSG(("%s: GPHY config done\n", __FUNCTION__)); + } + + /* Enable switch leds */ + if (BCM53573_CHIP(sih->chip)) { + uint32 led_gpios = 0; + const char *var; + + /* Support 53573 internal robo switch LED on/off after A1 chip revision */ + if (sih->chippkg != BCM47189_PKG_ID && sih->chiprev >= 1) { + /* In 53573, bit 0: gpio0..4, bit 2: gpio 5..9 */ + led_gpios = 0x5; + + var = getvar(vars, "et_swleds"); + if (var) { + led_gpios = bcm_strtoul(var, NULL, 0); + /* transfer nvram setting to register settings */ + led_gpios = (led_gpios < 2 ? led_gpios : led_gpios + 2); + } + } + if (PMUCTL_ENAB(sih)) { + si_pmu_chipcontrol(sih, 8, led_gpios, led_gpios); + } + } + +#ifndef _CFE_ + if (!robo->ops) { + int mosi, miso, ss, sck; + + robo->ops = &spigpio; + robo->devid = DEVID5325; + + /* Init GPIO mapping. Default 2, 3, 4, 5 */ + ss = getgpiopin(vars, "robo_ss", 2); + if (ss == GPIO_PIN_NOTDEFINED) { + ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use")); + goto error; + } + robo->ss = 1 << ss; + sck = getgpiopin(vars, "robo_sck", 3); + if (sck == GPIO_PIN_NOTDEFINED) { + ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use")); + goto error; + } + robo->sck = 1 << sck; + mosi = getgpiopin(vars, "robo_mosi", 4); + if (mosi == GPIO_PIN_NOTDEFINED) { + ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use")); + goto error; + } + robo->mosi = 1 << mosi; + miso = getgpiopin(vars, "robo_miso", 5); + if (miso == GPIO_PIN_NOTDEFINED) { + ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use")); + goto error; + } + robo->miso = 1 << miso; + ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__, + ss, sck, mosi, miso)); + } +#endif /* _CFE_ */ + + /* sanity check */ + ASSERT(robo->ops); + ASSERT(robo->ops->write_reg); + ASSERT(robo->ops->read_reg); + ASSERT((robo->devid == DEVID5325) || + (robo->devid == DEVID5395) || + (robo->devid == DEVID5397) || + (robo->devid == DEVID5398) || + (robo->devid == DEVID53115) || + (robo->devid == DEVID53125) || + ROBO_IS_BCM5301X(robo->devid)); + +#ifndef _CFE_ + /* nvram variable switch_mode controls the power save mode on the switch + * set the default value in the beginning + */ + robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual"); + robo->pwrsave_sleep_time = getintvar(robo->vars, "switch_pwrsave_sleep"); + if (robo->pwrsave_sleep_time == 0) + robo->pwrsave_sleep_time = PWRSAVE_SLEEP_TIME; + robo->pwrsave_wake_time = getintvar(robo->vars, "switch_pwrsave_wake"); + if (robo->pwrsave_wake_time == 0) + robo->pwrsave_wake_time = PWRSAVE_WAKE_TIME; + robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto"); + + /* Determining what all phys need to be included in + * power save operation + */ + et1port = getvar(vars, "et1mdcport"); + if (et1port) + mdcport = bcm_atoi(et1port); + + et1phyaddr = getvar(vars, "et1phyaddr"); + if (et1phyaddr) + phyaddr = bcm_atoi(et1phyaddr); + + if ((mdcport == 0) && (phyaddr == 4)) + /* For 5325F switch we need to do only phys 0-3 */ + robo->pwrsave_phys = 0xf; + else + /* By default all 5 phys are put into power save if there is no link */ + robo->pwrsave_phys = 0x1f; +#endif /* _CFE_ */ + +#ifdef BCMFA + robo->aux_pid = -1; + if (BCM4707_CHIP(CHIPID(robo->sih->chip))) { + if (getvar(robo->vars, "et0macaddr")) + robo->aux_pid = 5; /* unit 0 maps to port 5 */ + else if (getvar(robo->vars, "et1macaddr")) + robo->aux_pid = 7; /* unit 1 maps to port 7 */ + + ASSERT(robo->aux_pid != -1); + } +#endif /* BCMFA */ + + return robo; + +#ifndef _CFE_ +error: + bcm_robo_detach(robo); + return NULL; +#endif /* _CFE_ */ +} + +/* Release access to the RoboSwitch */ +void +bcm_robo_detach(robo_info_t *robo) +{ + if (SRAB_ENAB(robo->sih) && robo->srabregs) + REG_UNMAP(robo->srabregs); + + MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); +} + +/* Enable the device and set it to a known good state */ +int +bcm_robo_enable_device(robo_info_t *robo) +{ + uint8 reg_offset, reg_val; + int ret = 0; + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + if (robo->devid == DEVID5398) { + /* Disable unused ports: port 6 and 7 */ + for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) { + /* Set bits [1:0] to disable RX and TX */ + reg_val = 0x03; + robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, ®_val, + sizeof(reg_val)); + } + } + + if (robo->devid == DEVID5325) { + /* Must put the switch into Reverse MII mode! */ + + /* MII port state override (page 0 register 14) */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, ®_val, sizeof(reg_val)); + + /* Bit 4 enables reverse MII mode */ + if (!(reg_val & (1 << 4))) { + /* Enable RvMII */ + reg_val |= (1 << 4); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, ®_val, + sizeof(reg_val)); + + /* Read back */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, ®_val, + sizeof(reg_val)); + if (!(reg_val & (1 << 4))) { + ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n")); + ret = -1; + } + } + } + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); + + return ret; +} + +/* Port flags */ +#define FLAG_TAGGED 't' /* output tagged (external ports only) */ +#define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */ +#define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */ + +/* port descriptor */ +typedef struct { + uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */ + uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */ + uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */ + uint8 cpu; /* is this cpu port? */ +} pdesc_t; + +pdesc_t pdesc97[] = { + /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */ + /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0}, + /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0}, + /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0}, + /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0}, + /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0}, + /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0}, + /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0}, + /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0}, + /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1}, +}; + +pdesc_t pdesc25[] = { + /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0}, + /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0}, + /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0}, + /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0}, + /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0}, + /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1}, +}; + +#if !defined(_CFE_) && defined(BCMFA) +/* For FA feature can be worked with old/new CFE which keep using et0mac */ +static int +robo_fa_imp_port_upd(robo_info_t *robo, char *port, int pid, int vid, int pdescsz) +{ + int newpid = pid; + + if (pid == robo->aux_pid) { + if (BCM4707_CHIP(CHIPID(robo->sih->chip)) && (pid != pdescsz - 1) && + FA_ON(getintvar(robo->vars, "ctf_fa_mode"))) { + newpid = pdescsz - 1; + } + } + + return newpid; +} +#endif /* !_CFE_ && BCMFA */ + +/* Find the first vlanXXXXports which the last port include '*' or 'u' */ +static void +robo_cpu_port_upd(robo_info_t *robo, pdesc_t *pdesc, int pdescsz) +{ + int vid; + + for (vid = 0; vid < VLAN_NUMVLANS; vid ++) { + char vlanports[] = "vlanXXXXports"; + char port[] = "XXXX", *next; + const char *ports, *cur; + int pid, len; + + /* no members if VLAN id is out of limitation */ + if (vid > VLAN_MAXVID) + return; + + /* get vlan member ports from nvram */ + (void)snprintf(vlanports, sizeof(vlanports), "vlan%dports", vid); + ports = getvar(robo->vars, vlanports); + if (!ports) + continue; + + /* search last port include '*' or 'u' */ + for (cur = ports; cur; cur = next) { + /* tokenize the port list */ + while (*cur == ' ') + cur ++; + next = bcmstrstr(cur, " "); + len = next ? next - cur : strlen(cur); + if (!len) + break; + if (len > sizeof(port) - 1) + len = sizeof(port) - 1; + strncpy(port, cur, len); + port[len] = 0; + + /* make sure port # is within the range */ + pid = bcm_atoi(port); + if (pid >= pdescsz) { + ET_ERROR(("robo_cpu_upd: port %d in vlan%dports is out " + "of range[0-%d]\n", pid, vid, pdescsz)); + continue; + } + +#if !defined(_CFE_) && defined(BCMFA) + pid = robo_fa_imp_port_upd(robo, port, pid, vid, pdescsz); +#endif + if (strchr(port, FLAG_LAN) || strchr(port, FLAG_UNTAG)) { + /* Change it and return */ + pdesc[pid].cpu = 1; + } + } + } +} + +#if !defined(_CFE_) && defined(BCMFA) +/* Default assume: Do copy to aux port */ +static void +robo_fa_aux_set_action_policy(robo_info_t *robo, uint32 index) +{ + uint32 val32; + uint32 aux_portmap; + + /* bit[5:0]=p5~p0, bit6=p7, bit7=p8 */ + if (robo->aux_pid > 5) + aux_portmap = (1 << (robo->aux_pid - 1)); + else + aux_portmap = (1 << robo->aux_pid); + + /* Set to both in-band and out-band */ + + /* In-Band */ + val32 = ((3 << CFP_ACT_POL_DATA0_CFMI_SHIFT) | /* do copy */ + (aux_portmap << CFP_ACT_POL_DATA0_DMI_SHIFT) | /* aux port */ + 7); /* STP_BYP | EAP_BYP | VLAN_BYP */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACT_POL_DATA0, &val32, sizeof(val32)); + /* Out-Band */ + val32 = ((3 << CFP_ACT_POL_DATA1_CFMO_SHIFT) | /* do copy */ + (aux_portmap << CFP_ACT_POL_DATA1_DMO_SHIFT)); /* aux port */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACT_POL_DATA1, &val32, sizeof(val32)); + /* Issue write command */ + val32 = ((index << CFP_ACC_XCESS_ADDR_SHIFT) | /* index */ + (2 << CFP_ACC_RAM_SEL_SHIFT) | /* action/policy */ + (2 << CFP_ACC_OP_SEL_SHIFT) | /* write */ + CFP_ACC_OP_STR_DONE); /* operation start */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACC, &val32, sizeof(val32)); +} + +static void +robo_fa_aux_set_tcam(robo_info_t *robo, bool ipv6, bool tcp_rst, uint32 index) +{ + uint32 val32; + uint8 l3_framing_bit, tcp_flags_bit; + uint8 phy_portmap = 0x1F; /* port 0~4 by default */ + + if (ipv6) + l3_framing_bit = 1; /* IPv6 */ + else + l3_framing_bit = 0; /* IPv4 */ + + if (tcp_rst) + tcp_flags_bit = 4; /* RST */ + else + tcp_flags_bit = 1; /* FIN */ + + /* Both Data and Mask */ + /* DATA0 = UDF_n_A1(Low 8) + UDF_n_A0(16) + Reserved(4) + Slice_ID(2) + Vaild(2) */ + /* TCP flags bit (Host order) + Slice 0 + Vaild */ + val32 = ((tcp_flags_bit << 8) | (0 << 2) | 3); + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_DATA0, &val32, sizeof(val32)); + val32 = ((tcp_flags_bit << 8) | (3 << 2) | 3); + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_MASK0, &val32, sizeof(val32)); + /* DATA1 = UDF_n_A3(Low 8) + UDF_n_A2(16) + UDF_n_A1(High 8) */ + /* DATA2 = UDF_n_A5(Low 8) + UDF_n_A4(16) + UDF_n_A3(High 8) */ + /* DATA3 = UDF_n_A7(Low 8) + UDF_n_A6(16) + UDF_n_A5(High 8) */ + /* DATA4 = C_Tag(Low 8) + UDF_n_A8(16) + UDF_n_A7(High 8) */ + /* DATA5 = UDF_Valid [7:0](8) + S_Tag(16) + C_Tag(High 8) */ + val32 = (1 << 24); /* UDF_Valid[0] */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_DATA5, &val32, sizeof(val32)); + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_MASK5, &val32, sizeof(val32)); + /* DATA6 = STag_Status(2) + CTag_Status(2) + L2_Framing(2) + L3_Framing(2) + IP_TOS(8) + + * IP_Protocol(8) + IP_Fragmentation(1) + NonFirst_Fragment(1) + + * IP_Authentication(1) + TTL_Range(2) + Reserved(2) + UDF_Valid[8](1) + */ + val32 = ((l3_framing_bit << 24) | (6 << 8)); /* IPv4/6 TCP */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_DATA6, &val32, sizeof(val32)); + val32 = ((3 << 24) | (6 << 8)); + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_MASK6, &val32, sizeof(val32)); + /* DATA7 = SRC_PortMap */ + val32 = 0; + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_DATA7, &val32, sizeof(val32)); + val32 = 0xFF & ~phy_portmap; /* ~phy_portmap */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_MASK7, &val32, sizeof(val32)); + + /* Issue write command */ + val32 = ((index << CFP_ACC_XCESS_ADDR_SHIFT) | /* index */ + (1 << CFP_ACC_RAM_SEL_SHIFT) | /* TCAM */ + (2 << CFP_ACC_OP_SEL_SHIFT) | /* write */ + CFP_ACC_OP_STR_DONE); /* operation start */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACC, &val32, sizeof(val32)); +} + +#ifdef BCMDBG +static void +robo_fa_aux_dump_action_policy(robo_info_t *robo, struct bcmstrbuf *b, uint32 index, char *note) +{ + uint32 val32; + + /* Issue read command */ + val32 = ((index << CFP_ACC_XCESS_ADDR_SHIFT) | /* index */ + (2 << CFP_ACC_RAM_SEL_SHIFT) | /* action/policy */ + (1 << CFP_ACC_OP_SEL_SHIFT) | /* read */ + CFP_ACC_OP_STR_DONE); /* operation start */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACC, &val32, sizeof(val32)); + CFP_ACC_RD_STS_WAIT(robo, 2 /* action policy */); + + /* Dump both in-band and out-band */ + /* In-Band */ + val32 = 0; + robo->ops->read_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACT_POL_DATA0, &val32, sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP Action Policy In-Band index %d%s: 0x%08x\n", + PAGE_CFPTCAM, REG_CFPTCAM_ACT_POL_DATA0, index, + note ? note : "", val32); + /* Out-Band */ + val32 = 0; + robo->ops->read_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACT_POL_DATA1, &val32, sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP Action Policy Out-Band index %d%s: 0x%08x\n", + PAGE_CFPTCAM, REG_CFPTCAM_ACT_POL_DATA1, index, + note ? note : "", val32); +} + +static void +robo_fa_aux_dump_tcam(robo_info_t *robo, struct bcmstrbuf *b, uint32 index, char *note) +{ + int i; + uint32 val32; + uint32 tcam32[8]; + + /* Issue read command */ + val32 = ((index << CFP_ACC_XCESS_ADDR_SHIFT) | /* index */ + (1 << CFP_ACC_RAM_SEL_SHIFT) | /* TCAM */ + (1 << CFP_ACC_OP_SEL_SHIFT) | /* read */ + CFP_ACC_OP_STR_DONE); /* operation start */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACC, &val32, sizeof(val32)); + CFP_ACC_RD_STS_WAIT(robo, 1 /* TCAM */); + + /* Dump both Data and Mask */ + memset(tcam32, 0, sizeof(tcam32)); + for (i = 0; i < 8; i++) + robo->ops->read_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_DATA0+(4*i), &tcam32[i], + sizeof(tcam32[i])); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP TCAM Data index %d%s: 0x%08x 0x%08x 0x%08x " + "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x (LSB)\n", + PAGE_CFPTCAM, REG_CFPTCAM_DATA0, index, note ? note : "", + tcam32[7], tcam32[6], tcam32[5], tcam32[4], + tcam32[3], tcam32[2], tcam32[1], tcam32[0]); + memset(tcam32, 0, sizeof(tcam32)); + for (i = 0; i < 8; i++) + robo->ops->read_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_MASK0+(4*i), &tcam32[i], + sizeof(tcam32[i])); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP TCAM Mask index %d%s: 0x%08x 0x%08x 0x%08x " + "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x (LSB)\n", + PAGE_CFPTCAM, REG_CFPTCAM_MASK0, index, note ? note : "", + tcam32[7], tcam32[6], tcam32[5], tcam32[4], + tcam32[3], tcam32[2], tcam32[1], tcam32[0]); +} + +static void +robo_fa_aux_dump_rate_counter(robo_info_t *robo, struct bcmstrbuf *b, uint32 index, char *note) +{ + uint32 val32; + + /* Issue read command */ + val32 = ((index << CFP_ACC_XCESS_ADDR_SHIFT) | /* index */ + (0x10 << CFP_ACC_RAM_SEL_SHIFT) | /* out-band statistic */ + (1 << CFP_ACC_OP_SEL_SHIFT) | /* read */ + CFP_ACC_OP_STR_DONE); /* operation start */ + robo->ops->write_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_ACC, &val32, sizeof(val32)); + CFP_ACC_RD_STS_WAIT(robo, 8 /* band statistic */); + + /* Dump Out-Band Statistic */ + val32 = 0; + robo->ops->read_reg(robo, PAGE_CFPTCAM, REG_CFPTCAM_RATE_OUTBAND, &val32, sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP Rate Out-Band Statistic index %d%s: 0x%08x\n", + PAGE_CFPTCAM, REG_CFPTCAM_RATE_OUTBAND, index, + note ? note : "", val32); +} +#endif /* BCMDBG */ + +void +robo_fa_aux_init(robo_info_t *robo) +{ + uint8 val8; + + if (!robo) + return; + + if (robo->aux_pid == -1) { + ET_ERROR(("Invalid aux_pid\n")); + return; + } + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* AUX Port GMII Port States Override Register */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT0_GMIIPO + robo->aux_pid, + &val8, sizeof(val8)); + val8 |= + (1 << 7) | /* GMII_SPEED_UP_2G */ + (1 << 6) | /* SW_OVERRIDE */ + (1 << 5) | /* TXFLOW_CNTL */ + (1 << 4) | /* RXFLOW_CNTL */ + /* default(2 << 2) SPEED : + * 2b10 1000/2000Mbps + */ + /* default(1 << 1) DUPLX_MODE: + * Full Duplex + */ + (1 << 0); /* LINK_STS: Link up */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0_GMIIPO + robo->aux_pid, + &val8, sizeof(val8)); + + /* CFP: filter TCP FIN/RST and copy to AUX port */ + /* 1. Action policy */ + /* Index 0~4 (IPv4/6 TCP FIN/RST) */ + robo_fa_aux_set_action_policy(robo, 0); + robo_fa_aux_set_action_policy(robo, 1); + robo_fa_aux_set_action_policy(robo, 2); + robo_fa_aux_set_action_policy(robo, 3); + + /* 2. Data and Mask */ + /* Index 0~4 (IPv4/6 TCP FIN/RST) */ + robo_fa_aux_set_tcam(robo, FALSE, FALSE, 0); + robo_fa_aux_set_tcam(robo, FALSE, TRUE, 1); + robo_fa_aux_set_tcam(robo, TRUE, FALSE, 2); + robo_fa_aux_set_tcam(robo, TRUE, TRUE, 3); + + /* 3. UDFs */ + /* Slice 0 for IPv4/6 packet -FIN/RST */ + /* TCP flags offset 14 --> UDF offset start from 12 = 2N (N=6) */ + val8 = 0x60 | 0x6; + robo->ops->write_reg(robo, PAGE_CFP, REG_CFP_UDF_0_A_0_8, &val8, + sizeof(val8)); + robo->ops->write_reg(robo, PAGE_CFP, REG_CFP_UDF_0_A_0_8+1, &val8, + sizeof(val8)); + robo->ops->write_reg(robo, PAGE_CFP, REG_CFP_UDF_0_B_0_8, &val8, + sizeof(val8)); + robo->ops->write_reg(robo, PAGE_CFP, REG_CFP_UDF_0_B_0_8+1, &val8, + sizeof(val8)); + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); +} + +void +robo_fa_aux_enable(robo_info_t *robo, bool enable) +{ + uint8 val8 = 0x0; + uint8 phy_portmap = 0x1F; /* port 0~4 by default */ + + if (!robo) + return; + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* Enable CFP on phy ports */ + if (enable) + val8 = phy_portmap; + + robo->ops->write_reg(robo, PAGE_CFP, REG_CFP_CTL_REG, &val8, sizeof(val8)); + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); +} + +void +robo_fa_enable(robo_info_t *robo, bool on, bool bhdr) +{ + uint16 val16; + uint8 val8; + + if (!robo) + return; + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* BCM_HDR and OOB PAUSE */ + if (on) { + /* Enable BCM_HDR Tag on IMP port if need it. */ + val8 = (bhdr ? 0x1 : 0x0); + robo->ops->write_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); + + /* Use out-of-band signal for Switch and SOC flow control */ + robo->ops->read_reg(robo, PAGE_FC, REG_FC_OOBPAUSE, &val16, sizeof(val16)); + val16 |= (1 << 8); + robo->ops->write_reg(robo, PAGE_FC, REG_FC_OOBPAUSE, &val16, sizeof(val16)); + } + else { + /* Disable BRCM HDR */ + val8 = 0x0; + robo->ops->write_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); + + /* Default value: Use pause frame for Switch and SOC flow control. */ + robo->ops->read_reg(robo, PAGE_FC, REG_FC_OOBPAUSE, &val16, sizeof(val16)); + val16 &= ~(1 << 8); + robo->ops->write_reg(robo, PAGE_FC, REG_FC_OOBPAUSE, &val16, sizeof(val16)); + } + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); +} +#endif /* !_CFE_ && BCMFA */ + +/* Configure the VLANs */ +int +bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr) +{ + uint8 val8; + uint16 val16; + uint32 val32; + pdesc_t *pdesc; + int pdescsz; + uint16 vid; + uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 }; + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* setup global vlan configuration */ + /* VLAN Control 0 Register (Page 0x34, Address 0) */ + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); + val8 |= ((1 << 7) | /* enable 802.1Q VLAN */ + (3 << 5)); /* individual VLAN learning mode */ + if (robo->devid == DEVID5325) + val8 &= ~(1 << 1); /* must clear reserved bit 1 */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); + + /* VLAN Control 1 Register (Page 0x34, Address 1) */ + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); + val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */ + (1 << 3)); /* enable RSV multicast V Untagmap */ + if (robo->devid == DEVID5325) + val8 |= (1 << 1); /* enable RSV multicast V Tagging */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); + + arl_entry[0] = mac_addr[5]; + arl_entry[1] = mac_addr[4]; + arl_entry[2] = mac_addr[3]; + arl_entry[3] = mac_addr[2]; + arl_entry[4] = mac_addr[1]; + arl_entry[5] = mac_addr[0]; + + if (robo->devid == DEVID5325) { + /* Init the entry 1 of the bin */ + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, + arl_entry1, sizeof(arl_entry1)); + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, + arl_entry1, 1); + + /* Init the entry 0 of the bin */ + arl_entry[6] = 0x8; /* Port Id: MII */ + arl_entry[7] = 0xc0; /* Static Entry, Valid */ + + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, + arl_entry, sizeof(arl_entry)); + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, + arl_entry, ETHER_ADDR_LEN); + + /* VLAN Control 4 Register (Page 0x34, Address 4) */ + val8 = (1 << 6); /* drop frame with VID violation */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8)); + + /* VLAN Control 5 Register (Page 0x34, Address 5) */ + val8 = (1 << 3); /* drop frame when miss V table */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); + + pdesc = pdesc25; + pdescsz = sizeof(pdesc25) / sizeof(pdesc_t); + } else { + /* Initialize the MAC Addr Index Register */ + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, + arl_entry, ETHER_ADDR_LEN); + + pdesc = pdesc97; + pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); + + if ((SRAB_ENAB(robo->sih) && ROBO_IS_BCM5301X(robo->devid)) || + (BCM53573_CHIP(robo->sih->chip) && robo->sih->chippkg == BCM47189_PKG_ID)) { + robo_cpu_port_upd(robo, pdesc97, pdescsz); + } + } + + /* setup each vlan. max. 16 vlans. */ + /* force vlan id to be equal to vlan number */ + for (vid = 0; vid < VLAN_NUMVLANS; vid ++) { + char vlanports[] = "vlanXXXXports"; + char port[] = "XXXX", *next; + const char *ports, *cur; + uint32 untag = 0; + uint32 member = 0; + int pid, len; + int cpuport = 0; + + /* no members if VLAN id is out of limitation */ + if (vid > VLAN_MAXVID) + goto vlan_setup; + + /* get vlan member ports from nvram */ + (void)snprintf(vlanports, sizeof(vlanports), "vlan%dports", vid); + ports = getvar(robo->vars, vlanports); + + /* In 539x vid == 0 us invalid?? */ + if ((robo->devid != DEVID5325) && (vid == 0)) { + if (ports) + ET_ERROR(("VID 0 is set in nvram, Ignoring\n")); + continue; + } + + /* disable this vlan if not defined */ + if (!ports) + goto vlan_setup; + + /* + * setup each port in the vlan. cpu port needs special handing + * (with or without output tagging) to support linux/pmon/cfe. + */ + for (cur = ports; cur; cur = next) { + /* tokenize the port list */ + while (*cur == ' ') + cur ++; + next = bcmstrstr(cur, " "); + len = next ? next - cur : strlen(cur); + if (!len) + break; + if (len > sizeof(port) - 1) + len = sizeof(port) - 1; + strncpy(port, cur, len); + port[len] = 0; + + /* make sure port # is within the range */ + pid = bcm_atoi(port); + if (pid >= pdescsz) { + ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out " + "of range[0-%d]\n", pid, vid, pdescsz)); + continue; + } + + /* build VLAN registers values */ +#ifndef _CFE_ +#ifdef BCMFA + pid = robo_fa_imp_port_upd(robo, port, pid, vid, pdescsz); +#endif + if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) || + (pdesc[pid].cpu && strchr(port, FLAG_UNTAG))) +#endif /* !_CFE_ */ + untag |= pdesc[pid].untag; + + member |= pdesc[pid].member; + + /* set port tag - applies to untagged ingress frames */ + /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */ +#ifdef _CFE_ +#define FL FLAG_LAN +#else +#define FL FLAG_UNTAG +#endif /* _CFE_ */ + if (!pdesc[pid].cpu || strchr(port, FL)) { + val16 = ((0 << 13) | /* priority - always 0 */ + vid); /* vlan id */ + robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr, + &val16, sizeof(val16)); + } + + if (pdesc[pid].cpu) + cpuport = pid; + } + + /* Add static ARL entries */ + if (robo->devid == DEVID5325) { + val8 = vid; + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, + &val8, sizeof(val8)); + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, + &val8, sizeof(val8)); + + /* Write the entry */ + val8 = 0x80; + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, + &val8, sizeof(val8)); + /* Wait for write to complete */ + SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, + &val8, sizeof(val8)), ((val8 & 0x80) != 0)), + 100 /* usec */); + } else { + /* Set the VLAN Id in VLAN ID Index Register */ + val8 = vid; + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, + &val8, sizeof(val8)); + + /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0 + * Register. + */ + arl_entry[6] = vid; + arl_entry[7] = 0x0; + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, + arl_entry, sizeof(arl_entry)); + + /* Set the Static bit , Valid bit and Port ID fields in + * ARL Table Data Entry 0 Register + */ + val32 = 0x18000 + cpuport; + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, + &val32, sizeof(val32)); + + /* Clear the ARL_R/W bit and set the START/DONE bit in + * the ARL Read/Write Control Register. + */ + val8 = 0x80; + robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, + &val8, sizeof(val8)); + /* Wait for write to complete */ + SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, + &val8, sizeof(val8)), ((val8 & 0x80) != 0)), + 100 /* usec */); + } + +vlan_setup: + /* setup VLAN ID and VLAN memberships */ + + val32 = (untag | /* untag enable */ + member); /* vlan members */ + if (robo->devid == DEVID5325) { + if (robo->corerev < 3) { + val32 |= ((1 << 20) | /* valid write */ + ((vid >> 4) << 12)); /* vlan id bit[11:4] */ + } else { + val32 |= ((1 << 24) | /* valid write */ + (vid << 12)); /* vlan id bit[11:4] */ + } + ET_MSG(("bcm_robo_config_vlan: programming REG_VLAN_WRITE %08x\n", val32)); + + /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32, + sizeof(val32)); + /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */ + val16 = ((1 << 13) | /* start command */ + (1 << 12) | /* write state */ + vid); /* vlan id */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16, + sizeof(val16)); + } else { + uint8 vtble, vtbli, vtbla; + + if ((robo->devid == DEVID5395) || + (robo->devid == DEVID53115) || + (robo->devid == DEVID53125) || + ROBO_IS_BCM5301X(robo->devid)) { + vtble = REG_VTBL_ENTRY_5395; + vtbli = REG_VTBL_INDX_5395; + vtbla = REG_VTBL_ACCESS_5395; + } else { + vtble = REG_VTBL_ENTRY; + vtbli = REG_VTBL_INDX; + vtbla = REG_VTBL_ACCESS; + } + + /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ + robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32, + sizeof(val32)); + /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */ + val16 = vid; /* vlan id */ + robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, + sizeof(val16)); + + /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ + val8 = ((1 << 7) | /* start command */ + 0); /* write */ + robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, + sizeof(val8)); + } + } + + if (robo->devid == DEVID5325) { + /* + * FIXME: do we need to do this when prio re-map feature + * (bit[7] of page 0x34 addr 2) is disabled (0)??? + */ + /* setup priority mapping - applies to tagged ingress frames */ + /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */ + val32 = ((0 << 0) | /* 0 -> 0 */ + (1 << 3) | /* 1 -> 1 */ + (2 << 6) | /* 2 -> 2 */ + (3 << 9) | /* 3 -> 3 */ + (4 << 12) | /* 4 -> 4 */ + (5 << 15) | /* 5 -> 5 */ + (6 << 18) | /* 6 -> 6 */ + (7 << 21)); /* 7 -> 7 */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32)); + } + + if (robo->devid == DEVID53115) { + /* Configure the priority system to use to determine the TC of + * ingress frames. Use DiffServ TC mapping, otherwise 802.1p + * TC mapping, otherwise MAC based TC mapping. + */ + val8 = ((0 << 6) | /* Disable port based QoS */ + (2 << 2)); /* QoS priority selection */ + robo->ops->write_reg(robo, 0x30, 0, &val8, sizeof(val8)); + + /* Configure tx queues scheduling mechanism */ + val8 = (3 << 0); /* Strict priority */ + robo->ops->write_reg(robo, 0x30, 0x80, &val8, sizeof(val8)); + + /* Enable 802.1p Priority to TC mapping for individual ports */ + val16 = 0x11f; + robo->ops->write_reg(robo, 0x30, 0x4, &val16, sizeof(val16)); + + /* Configure the TC to COS mapping. This determines the egress + * transmit queue. + */ + val16 = ((1 << 0) | /* Pri 0 mapped to TXQ 1 */ + (0 << 2) | /* Pri 1 mapped to TXQ 0 */ + (0 << 4) | /* Pri 2 mapped to TXQ 0 */ + (1 << 6) | /* Pri 3 mapped to TXQ 1 */ + (2 << 8) | /* Pri 4 mapped to TXQ 2 */ + (2 << 10) | /* Pri 5 mapped to TXQ 2 */ + (3 << 12) | /* Pri 6 mapped to TXQ 3 */ + (3 << 14)); /* Pri 7 mapped to TXQ 3 */ + robo->ops->write_reg(robo, 0x30, 0x62, &val16, sizeof(val16)); + } + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); + + return 0; +} + +#define RSV_MCAST_CTRL_EN_MUL_1 1 /* RSV_MCAST_CTRL_EN_MUL_ bit 1 for 01:80:C2:00:00:02 - 0F */ +#define RSV_MCAST_CTRL_EN_MUL_3 3 /* RSV_MCAST_CTRL_EN_MUL_ bit 3 for 01:80:C2:00:00:11 - 1F */ + +static void +bcm_robo_config_mcast(robo_info_t *robo) +{ + uint8 val8 = 0; + + /* IMP0 Control Register (Page 0, Address 0x2f) */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_RSV_MCAST_CTRL, &val8, sizeof(val8)); + val8 &= (~((1 << RSV_MCAST_CTRL_EN_MUL_1) | (1 << RSV_MCAST_CTRL_EN_MUL_3))); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_RSV_MCAST_CTRL, &val8, sizeof(val8)); +} + +/* Enable switching/forwarding */ +int +bcm_robo_enable_switch(robo_info_t *robo) +{ + int i, max_port_ind, ret = 0; + uint8 val8; + uint16 val16; + uint8 im_mac[6] = {0x13, 0x00, 0x00, 0xC2, 0x80, 0x01}; + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* Switch Mode register (Page 0, Address 0x0B) */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); + + if (!mang_mode_en) { + /* Set unmanaged mode if no any other GMAC enable mang mode */ + val8 &= (~(1 << 0)); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); + } + + /* Bit 1 enables switching/forwarding */ + if (!(val8 & (1 << 1))) { + /* Set unmanaged mode */ + val8 &= (~(1 << 0)); + + /* Enable forwarding */ + val8 |= (1 << 1); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); + + /* Read back */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); + if (!(val8 & (1 << 1))) { + ET_ERROR(("robo_enable_switch: enabling forwarding failed\n")); + ret = -1; + } + + /* No spanning tree for unmanaged mode */ + val8 = 0; + if (robo->devid == DEVID5398 || ROBO_IS_BCM5301X(robo->devid)) + max_port_ind = REG_CTRL_PORT7; + else if (BCM53573_CHIP(robo->sih->chip) && robo->sih->chippkg == BCM47189_PKG_ID) + max_port_ind = REG_CTRL_PORT5; + else + max_port_ind = REG_CTRL_PORT4; + + for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) { + if (ROBO_IS_BCM5301X(robo->devid) && i == REG_CTRL_PORT6) + continue; + robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); + } + + /* No spanning tree on IMP port too */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); + } + + if (robo->devid == DEVID53125) { + /* Over ride IMP port status to make it link by default */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); + val8 |= 0xb1; /* Make Link pass and override it. */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); + /* Init the EEE feature */ + robo_eee_advertise_init(robo); +#ifndef _CFE_ + if (BCM53573_CHIP(robo->sih->chip) && robo->sih->chippkg == BCM47189_PKG_ID) { + /* Find the first cpu port and do software override from port 0 to 5 */ + for (i = 0; i < 6; i++) { + if (!pdesc97[i].cpu) + continue; + + /* Port 5 GMII Port States Override Register + * (Page 0, Address 0x5d) + */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT0_GMIIPO + i, + &val8, sizeof(val8)); + val8 |= + (1 << 6) | /* SW_OVERRIDE */ + (1 << 5) | /* TXFLOW_CNTL */ + (1 << 4) | /* RXFLOW_CNTL */ + /* default(2 << 2) SPEED : + * 2b10 1000Mbps + */ + /* default(1 << 1) DUPLX_MODE: + * Full Duplex + */ + (1 << 0); /* LINK_STS: Link up */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0_GMIIPO + i, + &val8, sizeof(val8)); + } + } +#endif /* !CFE */ + } + + if (SRAB_ENAB(robo->sih) && ROBO_IS_BCM5301X(robo->devid)) { + int pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); + +#ifdef CFG_SIM + /* Over ride Port0 ~ Port4 status to make it link by default */ + /* (Port0 ~ Port4) LINK_STS bit default is 0x1(link up), do it anyway */ + for (i = REG_CTRL_PORT0_GMIIPO; i <= REG_CTRL_PORT4_GMIIPO; i++) { + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); + val8 |= 0x71; /* Make it link by default. */ + robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); + } +#endif + + /* Find the first cpu port and do software override */ + for (i = 0; i < pdescsz; i++) { + /* Port 6 is not able to use */ + if (i == 6 || !pdesc97[i].cpu) + continue; + + if (i == pdescsz - 1) { /* Port8: REG_CTRL_MIIPO */ + /* Port 8 IMP Port States Override Register (Page 0, Address 0xe) */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, + &val8, sizeof(val8)); + val8 |= + (1 << 7) | /* MII_SW_OR MII Software Override */ + (1 << 6) | /* GMII_SPEED_UP_2G */ + (1 << 5) | /* TXFLOW_CNTL */ + (1 << 4) | /* RXFLOW_CNTL */ + /* default(2 << 2) SPEED : + * 2b10 1000/2000Mbps + */ + /* default(1 << 1) DUPLX_MODE: + * Full Duplex + */ + (1 << 0); /* LINK_STS: Link up */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, + &val8, sizeof(val8)); + + /* Port8 IMP0 Control Register (Page 0, Address 0x08) */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_IMP, + &val8, sizeof(val8)); + val8 |= + (1 << 4) | /* RX_UCST_EN Receive Unicast Enable */ + (1 << 3) | /* RX_MCST_EN Receive Multicast Enable */ + (1 << 2); /* RX_BCST_EN Receive Broadcast Enable */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, + &val8, sizeof(val8)); + + /* XXX: Packets with DA as 1905 Reserved Multicast addr + * 01:80:C2:00:00:13 are not recieved by IMP port in Managed mode + * Configuring IMP port as mirror port with rule to recieve packets + * with DA - 01:80:C2:00:00:13 + */ + val16 = + (1 << 15) | /* MIR_EN Enable mirroring */ + (8 << 0); /* SMIR_CAP_PORT Configuring IMP port + * as Mirror capture port + */ + /* Mirror Capture Control Regiter (Page 2, Address 0x10) */ + robo->ops->write_reg(robo, PAGE_MMR, REG_MMR_MCCR, + &val16, sizeof(val16)); + val16 = + (1 << 14) | /* IN_MIT_FLTR Mirror frames with DA */ + (0xBE << 0); /* IN_MIR_MSK: Ingress frames ports 1-5,7 */ + + /* Ingress Mirror Control Register (Page 2, Address 0x12) */ + robo->ops->write_reg(robo, PAGE_MMR, REG_MMR_IMCR, + &val16, sizeof(val16)); + + /* Ingress Mirror MAC Register (Page 2, Address 0x16) */ + robo->ops->write_reg(robo, PAGE_MMR, REG_MMR_IMMAC, + im_mac, ETHER_ADDR_LEN); + + /* For multicast layer2 forwarding - 01-80-c2-00-00- 13/0e */ + bcm_robo_config_mcast(robo); + + /* Global Management Configuration Register (Page 2, Address 0x0) */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, + &val8, sizeof(val8)); + val8 |= + (2 << 6); /* FRM_MNGP: Enable IMP0 only */ + robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, + &val8, sizeof(val8)); + + /* 802.1Q VLAN Control 5 Register (Page 0x34, Address 0x06) */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, + &val8, sizeof(val8)); + val8 |= (1 << 0); /* EN_CPU_RX_BYP_INNER_CRC_CHK: + * IMP port ignore CRC + */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, + &val8, sizeof(val8)); + + /* Switch Mode Register (Page 0, Address 0x0B): Set Managed Mode */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, + &val8, sizeof(val8)); + val8 |= (1 << 0); /* SW_FWDG_MODE Managed Mode */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, + &val8, sizeof(val8)); + mang_mode_en = TRUE; + + /* BCM_GMAC3: Enable ports 5 and 7 for SMP dual core 3 GMAC setup */ + + /* Port 5 GMII Port States Override Register + * (Page 0, Address 0x5d) + */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, + &val8, sizeof(val8)); +#if defined(BCM_GMAC3) + val8 |= + (1 << 7) | /* GMII_SPEED_UP_2G */ + (1 << 6) | /* SW_OVERRIDE */ + (1 << 5) | /* TXFLOW_CNTL */ + (1 << 4) | /* RXFLOW_CNTL */ + /* default(2 << 2) SPEED : + * 2b10 1000/2000Mbps + */ + /* default(1 << 1) DUPLX_MODE: + * Full Duplex + */ + (1 << 0); /* LINK_STS: Link up */ +#else /* ! BCM_GMAC3 */ + val8 &= ~(1 << 0); +#endif /* ! BCM_GMAC3 */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, + &val8, sizeof(val8)); + + /* Port 7 GMII Port States Override Register + * (Page 0, Address 0x5f) + */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, + &val8, sizeof(val8)); +#if defined(BCM_GMAC3) + val8 |= + (1 << 7) | /* GMII_SPEED_UP_2G */ + (1 << 6) | /* SW_OVERRIDE */ + (1 << 5) | /* TXFLOW_CNTL */ + (1 << 4) | /* RXFLOW_CNTL */ + /* default(2 << 2) SPEED : + * 2b10 1000/2000Mbps + */ + /* default(1 << 1) DUPLX_MODE: + * Full Duplex + */ + (1 << 0); /* LINK_STS: Link up */ +#else /* ! BCM_GMAC3 */ + val8 &= ~(1 << 0); +#endif /* ! BCM_GMAC3 */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, + &val8, sizeof(val8)); + } else { /* Port5|7: REG_CTRL_PORT0_GMIIPO + i */ + + /* Port 5|7 GMII Port States Override Register + * (Page 0, Address 0x5d|0x5f) + */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT0_GMIIPO + i, + &val8, sizeof(val8)); + val8 |= + (1 << 7) | /* GMII_SPEED_UP_2G */ + (1 << 6) | /* SW_OVERRIDE */ + (1 << 5) | /* TXFLOW_CNTL */ + (1 << 4) | /* RXFLOW_CNTL */ + /* default(2 << 2) SPEED : + * 2b10 1000/2000Mbps + */ + /* default(1 << 1) DUPLX_MODE: + * Full Duplex + */ + (1 << 0); /* LINK_STS: Link up */ + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT0_GMIIPO + i, + &val8, sizeof(val8)); + + /* For multicast layer2 forwarding - 01-80-c2-00-00- 13/0e */ + bcm_robo_config_mcast(robo); + } + break; + } + + /* BRCM HDR Control Register (Page 2, Address 0x03) */ + val8 = 0x0; /* Disable BRCM HDR by default */ + robo->ops->write_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); + + /* Disable CFP by default */ + val8 = 0x0; + robo->ops->write_reg(robo, PAGE_CFP, REG_CFP_CTL_REG, &val8, sizeof(val8)); + } + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); + + return ret; +} + +#ifdef BCMDBG +void +robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b) +{ + uint8 val8; + uint16 val16; + uint32 val32; + pdesc_t *pdesc; + int pdescsz; + int i; + + bcm_bprintf(b, "%s:\n", robo->ops->desc); + if (robo->miird == NULL) { + bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n", + robo->ss, robo->sck, robo->mosi, robo->miso); + } + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* Dump registers interested */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8); + if (robo->devid == DEVID5325) { + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x00,0x0E)MII port state override regsiter: 0x%02x\n", val8); + } + if (robo->miird == NULL) + goto exit; + if (robo->devid == DEVID5325) { + pdesc = pdesc25; + pdescsz = sizeof(pdesc25) / sizeof(pdesc_t); + } else { + pdesc = pdesc97; + pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); + } + + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8); + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8); + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8)); + if (robo->devid == DEVID5325) { + bcm_bprintf(b, "(0x34,0x04)VLAN control 4 register: 0x%02x\n", val8); + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x34,0x05)VLAN control 5 register: 0x%02x\n", val8); + + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32)); + bcm_bprintf(b, "(0x34,0x20)Prio Re-map: 0x%08x\n", val32); + + for (i = 0; i <= VLAN_MAXVID; i++) { + val16 = (1 << 13) /* start command */ + | i; /* vlan id */ + robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16, + sizeof(val16)); + robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_READ, &val32, sizeof(val32)); + bcm_bprintf(b, "(0x34,0xc)VLAN %d untag bits: 0x%02x member bits: 0x%02x\n", + i, (val32 & 0x0fc0) >> 6, (val32 & 0x003f)); + } + + } else { + uint8 vtble, vtbli, vtbla; + + if ((robo->devid == DEVID5395) || + (robo->devid == DEVID53115) || + (robo->devid == DEVID53125) || + ROBO_IS_BCM5301X(robo->devid)) { + vtble = REG_VTBL_ENTRY_5395; + vtbli = REG_VTBL_INDX_5395; + vtbla = REG_VTBL_ACCESS_5395; + } else { + vtble = REG_VTBL_ENTRY; + vtbli = REG_VTBL_INDX; + vtbla = REG_VTBL_ACCESS; + } + + for (i = 0; i <= VLAN_MAXVID; i++) { + /* + * VLAN Table Address Index Register + * (Page 0x05, Address 0x61-0x62/0x81-0x82) + */ + val16 = i; /* vlan id */ + robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, + sizeof(val16)); + /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ + val8 = ((1 << 7) | /* start command */ + 1); /* read */ + robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, + sizeof(val8)); + /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ + robo->ops->read_reg(robo, PAGE_VTBL, vtble, &val32, + sizeof(val32)); + bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n", + i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff)); + } + } + for (i = 0; i < pdescsz; i++) { + robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16)); + bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16); + } + + if (SRAB_ENAB(robo->sih) && ROBO_IS_BCM5301X(robo->devid)) { + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port 5 States Override: 0x%02x\n", + PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, val8); + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port 7 States Override: 0x%02x\n", + PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, val8); + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port 8 States Override: 0x%02x\n", + PAGE_CTRL, REG_CTRL_MIIPO, val8); + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port 8 IMP Control Register: 0x%02x\n", + PAGE_CTRL, REG_CTRL_IMP, val8); + robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) Global Management Config: 0x%02x\n", + PAGE_MMR, REG_MGMT_CFG, val8); + robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) 802.1Q VLAN Control 5: 0x%02x\n", + PAGE_MMR, REG_MGMT_CFG, val8); + robo->ops->read_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) BRCM HDR Control Register: 0x%02x\n", + PAGE_MMR, REG_BRCM_HDR, val8); + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) Switch Mode Register: 0x%02x\n", + PAGE_CTRL, REG_CTRL_MODE, val8); + +#ifdef BCMFA + /* Dump CFP */ + bcm_bprintf(b, "\n Switch CFP Dump\n"); + + /* Port CFP Enabled */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CFP, REG_CFP_CTL_REG, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP Enable Map: 0x%02x\n", + PAGE_CFP, REG_CFP_CTL_REG, val8); + + /* Action policy */ + /* Index 0~4 (IPv4/6 TCP FIN/RST) */ + robo_fa_aux_dump_action_policy(robo, b, 0, " (IPv4 TCP FIN)"); + robo_fa_aux_dump_action_policy(robo, b, 1, " (IPv4 TCP RST)"); + robo_fa_aux_dump_action_policy(robo, b, 2, " (IPv6 TCP FIN)"); + robo_fa_aux_dump_action_policy(robo, b, 3, " (IPv6 TCP RST)"); + + /* Data and Mask */ + /* IPv4 index 0~4 (IPv4/6 TCP FIN/RST) */ + robo_fa_aux_dump_tcam(robo, b, 0, " (IPv4 TCP FIN)"); + robo_fa_aux_dump_tcam(robo, b, 1, " (IPv4 TCP RST)"); + robo_fa_aux_dump_tcam(robo, b, 2, " (IPv6 TCP FIN)"); + robo_fa_aux_dump_tcam(robo, b, 3, " (IPv6 TCP RST)"); + + /* UDFs */ + /* Slice 0 for IPv4 packet -FIN */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CFP, REG_CFP_UDF_0_A_0_8, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP UDF_0_A_0_0 Offset (IPv4 TCP FIN): 0x%02x\n", + PAGE_CFP, REG_CFP_UDF_0_A_0_8, val8); + /* Slice 0 for IPv4 packet -RST */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CFP, REG_CFP_UDF_0_A_0_8+1, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP UDF_0_A_0_1 Offset (IPv4 TCP RST): 0x%02x\n", + PAGE_CFP, REG_CFP_UDF_0_A_0_8+1, val8); + /* Slice 0 for IPv6 packet -FIN */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CFP, REG_CFP_UDF_0_B_0_8, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP UDF_0_B_0_0 Offset (IPv6 TCP FIN): 0x%02x\n", + PAGE_CFP, REG_CFP_UDF_0_B_0_8, val8); + /* Slice 0 for IPv6 packet -RST */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CFP, REG_CFP_UDF_0_B_0_8+1, &val8, sizeof(val8)); + bcm_bprintf(b, "(0x%02x,0x%02x) CFP UDF_0_B_0_1 Offset (IPv6 TCP RST): 0x%02x\n", + PAGE_CFP, REG_CFP_UDF_0_B_0_8+1, val8); + + /* Statistic */ + robo_fa_aux_dump_rate_counter(robo, b, 0, " (IPv4 TCP FIN)"); + robo_fa_aux_dump_rate_counter(robo, b, 1, " (IPv4 TCP RST)"); + robo_fa_aux_dump_rate_counter(robo, b, 2, " (IPv6 TCP FIN)"); + robo_fa_aux_dump_rate_counter(robo, b, 3, " (IPv6 TCP RST)"); +#endif /* BCMFA */ + } +#ifndef _CFE_ + else if (robo->devid == DEVID53125) { + uint8 port_mib_page[] = { PAGE_MIB_P0, PAGE_MIB_P1, PAGE_MIB_P2, PAGE_MIB_P3, + PAGE_MIB_P4, PAGE_MIB_P5, PAGE_MIB_P6, PAGE_MIB_P7, PAGE_MIB_P8 }; + int port_mib_page_sz = sizeof(port_mib_page) / sizeof(port_mib_page[0]); + + /* Dump MIB registers interested */ + for (i = 0; i < port_mib_page_sz; i++) { + uint8 page = port_mib_page[i]; + + /* Skip port 6 and port 7 for 47189 since they are not used */ + if (i == 6 || i == 7) + continue; + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXDROPPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_drop_pkts: %d\n", + page, REG_MIB_TXDROPPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXQ0PKT, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_q0_pkts: %d\n", + page, REG_MIB_TXQ0PKT, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXBCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_broadcast_pkts: %d\n", + page, REG_MIB_TXBCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXMCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_multicast_pkts: %d\n", + page, REG_MIB_TXMCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXUCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_unicast_pkts: %d\n", + page, REG_MIB_TXUCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXDISCARD, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_discard_pkts: %d\n", + page, REG_MIB_TXDISCARD, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_TXPAUSEPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_pause_pkts: %d\n", + page, REG_MIB_TXPAUSEPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXUNDERSZPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d tx_undersize_pkts: %d\n", + page, REG_MIB_RXUNDERSZPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXPAUSEPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_pause_pkts: %d\n", + page, REG_MIB_RXPAUSEPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXOVERSZPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_oversize_pkts: %d\n", + page, REG_MIB_RXOVERSZPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXJABBERS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_jabbers: %d\n", + page, REG_MIB_RXJABBERS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXALIGNERROR, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_alignment_error: %d\n", + page, REG_MIB_RXALIGNERROR, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXFCSERROR, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_fcs_error: %d\n", + page, REG_MIB_RXFCSERROR, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXDROPPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_drop_pkts: %d\n", + page, REG_MIB_RXDROPPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXUCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_unicast_pkts: %d\n", + page, REG_MIB_RXUCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXMCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_multicast_pkts: %d\n", + page, REG_MIB_RXMCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXBCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_broadcast_pkts: %d\n", + page, REG_MIB_RXBCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXFRAGMENTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_fragment: %d\n", + page, REG_MIB_RXFRAGMENTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_RXDISCARD, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x)Port %d rx_discard_pkts: %d\n", + page, REG_MIB_RXDISCARD, i, val32); + } + } + else if (robo->devid == DEVID5325) { + uint8 port_mib_page[] = { PAGE_MIB_P0, PAGE_MIB_P1, PAGE_MIB_P2, PAGE_MIB_P3, + PAGE_MIB_P4, PAGE_MIB_P8 }; + int port_mib_page_sz = sizeof(port_mib_page) / sizeof(port_mib_page[0]); + uint16 mib_group_sel = 0; + + robo->ops->read_reg(robo, PAGE_MMR, REG_MIB_5325E_MODESEL, &mib_group_sel, + sizeof(val16)); + + /* Dump MIB registers interested */ + for (i = 0; i < port_mib_page_sz; i++) { + uint8 page = port_mib_page[i]; + + if ((mib_group_sel & (0x1 << i)) == 0) { + /* replace index 5 to 8 for IMP port */ + if (i == 5) + i = 8; + + /* MIB Group 0 counters */ + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_TXGOODPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d tx_good_pkts: %d\n", + page, REG_MIB_5325E_TXGOODPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_TXUCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d tx_unicast_pkts: %d\n", + page, REG_MIB_5325E_TXUCPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_RXGOODPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d rx_good_pkts: %d\n", + page, REG_MIB_5325E_RXGOODPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_RXUCPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d rx_unicast_pkts: %d\n", + page, REG_MIB_5325E_RXUCPKTS, i, val32); + } + else { + /* replace index 5 to 8 for IMP port */ + if (i == 5) + i = 8; + + /* MIB Group 1 counters */ + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_TXCOLBYTES, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d tx_collision_bytes: %d\n", + page, REG_MIB_5325E_TXCOLBYTES, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_TXOCTETBYTES, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d tx_octet_bytes: %d\n", + page, REG_MIB_5325E_TXOCTETBYTES, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_RXFCSERRPKTS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d rx_fcserror_pkts: %d\n", + page, REG_MIB_5325E_RXFCSERRPKTS, i, val32); + + val32 = 0; + robo->ops->read_reg(robo, page, REG_MIB_5325E_RXGOODOCTETS, &val32, + sizeof(val32)); + bcm_bprintf(b, "(0x%02x,0x%02x), Port %d Rx_octet_bytes: %d\n", + page, REG_MIB_5325E_RXGOODOCTETS, i, val32); + } + } + } +#endif /* !_CFE_ */ + +exit: + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); +} +#endif /* BCMDBG */ + +#ifndef _CFE_ +/* + * Update the power save configuration for ports that changed link status. + */ +void +robo_power_save_mode_update(robo_info_t *robo) +{ + uint phy; + + for (phy = 0; phy < MAX_NO_PHYS; phy++) { + if (robo->pwrsave_mode_auto & (1 << phy)) { + ET_MSG(("%s: set port %d to auto mode\n", + __FUNCTION__, phy)); + robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy); + } + } + + return; +} + +static int32 +robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy) +{ + uint16 val16; + + if (robo->devid == DEVID53115 || robo->devid == DEVID53125) { + /* For 53115/53125, 0x1C is the MII address of the auto power + * down register. Bit 5 is enabling the mode + * bits has the following purpose + * 15 - write enable 10-14 shadow register select 01010 for + * auto power 6-9 reserved 5 auto power mode enable + * 4 sleep timer select : 1 means 5.4 sec + * 0-3 wake up timer select: 0xF 1.26 sec + */ + val16 = 0xa800; + robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, val16); + } else if (BCM53573_CHIP(robo->sih->chip)) { + /* To disable auto power down mode + * clear bit 5 of Aux Status 2 register + * (Shadow reg 0x1b). Shadow register + * access is enabled by writing + * 1 to bit 7 of MII register 0x1f. + */ + val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST); + robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST, + (val16 | (1 << 7))); + + /* Disable auto power down by clearing + * bit 5 of to Aux Status 2 reg. + */ + val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2); + robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2, + (val16 & ~(1 << 5))); + + /* Undo shadow access */ + val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST); + robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST, + (val16 & ~(1 << 7))); + } else + return -1; + + robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_AUTO; + + return 0; +} + +static int32 +robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy) +{ + uint8 val8; + uint16 val16; + + if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) { + /* For 53115 0x0 is the MII control register + * Bit 11 is the power down mode bit + */ + val16 = robo->miird(robo->h, phy, REG_MII_CTRL); + val16 &= 0xf7ff; + robo->miiwr(robo->h, phy, REG_MII_CTRL, val16); + } else if (ROBO_IS_BCM5301X(robo->devid)) { + robo->ops->read_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16)); + val16 &= 0xf7ff; + robo->ops->write_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16)); + } else if (robo->devid == DEVID5325) { + if (phy == 0) + return -1; + /* For 5325 page 0x00 address 0x0F is the power down + * mode register. Bits 1-4 determines which of the + * phys are enabled for this mode + */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, + &val8, sizeof(val8)); + val8 &= ~(0x1 << phy); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, + &val8, sizeof(val8)); + } else + return -1; + + robo->pwrsave_mode_phys[phy] &= ~ROBO_PWRSAVE_MANUAL; + + return 0; +} + +/* + * Function which periodically checks the power save mode on the switch + */ +int32 +robo_power_save_toggle(robo_info_t *robo, int32 normal) +{ + int32 phy; + uint16 link_status; + + /* read the link status of all ports */ + robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, + &link_status, sizeof(uint16)); + link_status &= 0x1f; + + /* Take the phys out of the manual mode first so that link status + * can be checked. Once out of that mode check the link status + * and if any of the link is up do not put that phy into + * manual power save mode + */ + for (phy = 0; phy < MAX_NO_PHYS; phy++) { + /* When auto+manual modes are enabled we toggle between + * manual and auto modes. When only manual mode is enabled + * we toggle between manual and normal modes. When only + * auto mode is enabled there is no need to do anything + * here since auto mode is one time config. + */ + if ((robo->pwrsave_phys & (1 << phy)) && + (robo->pwrsave_mode_manual & (1 << phy))) { + if (!normal) { + /* Take the port out of the manual mode */ + robo_power_save_mode_clear_manual(robo, phy); + } else { + /* If the link is down put it back to manual else + * remain in the current state + */ + if (!(link_status & (1 << phy))) { + ET_MSG(("%s: link down, set port %d to man mode\n", + __FUNCTION__, phy)); + robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy); + } + } + } + } + + return 0; +} + +/* + * Switch the ports to normal mode. + */ +static int32 +robo_power_save_mode_normal(robo_info_t *robo, int32 phy) +{ + int32 error = 0; + + /* If the phy in the power save mode come out of it */ + switch (robo->pwrsave_mode_phys[phy]) { + case ROBO_PWRSAVE_AUTO_MANUAL: + error = robo_power_save_mode_clear_auto(robo, phy); + if (error == -1) + break; + + error = robo_power_save_mode_clear_manual(robo, phy); + break; + case ROBO_PWRSAVE_AUTO: + error = robo_power_save_mode_clear_auto(robo, phy); + break; + case ROBO_PWRSAVE_MANUAL: + error = robo_power_save_mode_clear_manual(robo, phy); + break; + + default: + break; + } + + return error; +} + +/* + * Switch all the inactive ports to auto power down mode. + */ +static int32 +robo_power_save_mode_auto(robo_info_t *robo, int32 phy) +{ + uint16 val16; + + /* If the switch supports auto power down enable that */ + if (robo->devid == DEVID53115 || robo->devid == DEVID53125) { + /* For 53115 0x1C is the MII address of the auto power + * down register. Bit 5 is enabling the mode + * bits has the following purpose + * 15 - write enable 10-14 shadow register select 01010 for + * auto power 6-9 reserved 5 auto power mode enable + * 4 sleep timer select: 0 means 2.7 sec, 1 means 5.4 sec + * 0-3 wake up timer select: 0x1: 84 ms, 0xF: 1.26 sec + */ + if (robo->devid == DEVID53125) + robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, 0xA831); + else + robo->miiwr(robo->h, phy, REG_MII_AUTO_PWRDOWN, 0xA83F); + } else if (BCM53573_CHIP(robo->sih->chip)) { + /* To enable auto power down mode set bit 5 of + * Auxillary Status 2 register (Shadow reg 0x1b) + * Shadow register access is enabled by writing + * 1 to bit 7 of MII register 0x1f. + */ + val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST); + robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST, + (val16 | (1 << 7))); + + /* Enable auto power down by writing to Auxillary + * Status 2 reg. + * Bit[5]: 0 for APD disable, 1 for APD enable + * Bit[4]: APD sleep time, 0 for 2.5 sec, 1 for 5 sec + * Bit[3:0]: APD wakeup time, 1 for 40 ms + */ + val16 = robo->miird(robo->h, phy, REG_MII_AUX_STATUS2); + if (BCM53573_CHIP(robo->sih->chip)) { + val16 &= ~0xF; + val16 |= (1 << 5) | (1 << 4) | 0x1; + } else + val16 |= (1 << 5); + robo->miiwr(robo->h, phy, REG_MII_AUX_STATUS2, val16); + + /* Undo shadow access */ + val16 = robo->miird(robo->h, phy, REG_MII_BRCM_TEST); + robo->miiwr(robo->h, phy, REG_MII_BRCM_TEST, + (val16 & ~(1 << 7))); + } else + return -1; + + robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_AUTO; + + return 0; +} + +/* + * Switch all the inactive ports to manual power down mode. + */ +static int32 +robo_power_save_mode_manual(robo_info_t *robo, int32 phy) +{ + uint8 val8; + uint16 val16; + + /* For both 5325 and 53115 the link status register is the same */ + robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, + &val16, sizeof(val16)); + if (val16 & (0x1 << phy)) + return 0; + + /* If the switch supports manual power down enable that */ + if ((robo->devid == DEVID53115) || (robo->devid == DEVID53125)) { + /* For 53115 0x0 is the MII control register bit 11 is the + * power down mode bit + */ + val16 = robo->miird(robo->h, phy, REG_MII_CTRL); + robo->miiwr(robo->h, phy, REG_MII_CTRL, val16 | 0x800); + } else if (ROBO_IS_BCM5301X(robo->devid)) { + robo->ops->read_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16)); + val16 |= 0x800; + robo->ops->write_reg(robo, 0x10+phy, 0x00, &val16, sizeof(val16)); + } else if (robo->devid == DEVID5325) { + if (phy == 0) + return -1; + /* For 5325 page 0x00 address 0x0F is the power down mode + * register. Bits 1-4 determines which of the phys are enabled + * for this mode + */ + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8, + sizeof(val8)); + val8 |= (1 << phy); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PWRDOWN, &val8, + sizeof(val8)); + } else + return -1; + + robo->pwrsave_mode_phys[phy] |= ROBO_PWRSAVE_MANUAL; + + return 0; +} + +/* + * Set power save modes on the robo switch + */ +int32 +robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy) +{ + int32 error = -1; + + if (phy > MAX_NO_PHYS) { + ET_ERROR(("Passed parameter phy is out of range\n")); + return -1; + } + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + switch (mode) { + case ROBO_PWRSAVE_NORMAL: + /* If the phy in the power save mode come out of it */ + error = robo_power_save_mode_normal(robo, phy); + break; + + case ROBO_PWRSAVE_AUTO_MANUAL: + error = robo_power_save_mode_auto(robo, phy); + if (error == -1) + break; + + error = robo_power_save_mode_manual(robo, phy); + break; + + case ROBO_PWRSAVE_AUTO: + error = robo_power_save_mode_auto(robo, phy); + break; + + case ROBO_PWRSAVE_MANUAL: + error = robo_power_save_mode_manual(robo, phy); + break; + + default: + break; + } + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); + + return error; +} + +/* + * Get the current power save mode of the switch ports. + */ +int32 +robo_power_save_mode_get(robo_info_t *robo, int32 phy) +{ + ASSERT(robo); + + if (phy >= MAX_NO_PHYS) + return -1; + + return robo->pwrsave_mode_phys[phy]; +} + +/* + * Configure the power save mode for the switch ports. + */ +int32 +robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy) +{ + int32 error; + + ASSERT(robo); + + if (phy >= MAX_NO_PHYS) + return -1; + + error = robo_power_save_mode(robo, mode, phy); + + if (error) + return error; + + if (mode == ROBO_PWRSAVE_NORMAL) { + robo->pwrsave_mode_manual &= ~(1 << phy); + robo->pwrsave_mode_auto &= ~(1 << phy); + } else if (mode == ROBO_PWRSAVE_AUTO) { + robo->pwrsave_mode_auto |= (1 << phy); + robo->pwrsave_mode_manual &= ~(1 << phy); + robo_power_save_mode_clear_manual(robo, phy); + } else if (mode == ROBO_PWRSAVE_MANUAL) { + robo->pwrsave_mode_manual |= (1 << phy); + robo->pwrsave_mode_auto &= ~(1 << phy); + robo_power_save_mode_clear_auto(robo, phy); + } else { + robo->pwrsave_mode_auto |= (1 << phy); + robo->pwrsave_mode_manual |= (1 << phy); + } + + return 0; +} +#endif /* _CFE_ */ + +/* BCM53125 EEE IOP WAR for some other vendor's wrong EEE implementation. */ + +static void +robo_link_down(robo_info_t *robo, int32 phy) +{ + if (robo->devid != DEVID53125) + return; + + printf("robo_link_down: applying EEE WAR for 53125 port %d link-down\n", phy); + + robo->miiwr(robo->h, phy, 0x18, 0x0c00); + robo->miiwr(robo->h, phy, 0x17, 0x001a); + robo->miiwr(robo->h, phy, 0x15, 0x0007); + robo->miiwr(robo->h, phy, 0x18, 0x0400); +} + +static void +robo_link_up(robo_info_t *robo, int32 phy) +{ + if (robo->devid != DEVID53125) + return; + + printf("robo_link_down: applying EEE WAR for 53125 port %d link-up\n", phy); + + robo->miiwr(robo->h, phy, 0x18, 0x0c00); + robo->miiwr(robo->h, phy, 0x17, 0x001a); + robo->miiwr(robo->h, phy, 0x15, 0x0003); + robo->miiwr(robo->h, phy, 0x18, 0x0400); +} + +void +robo_watchdog(robo_info_t *robo) +{ + int32 phy; + uint16 link_status; + static int first = 1; + + if (robo->devid != DEVID53125) + return; + + if (!robo->eee_status) + return; + + /* read the link status of all ports */ + robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, + &link_status, sizeof(uint16)); + link_status &= 0x1f; + if (first || (link_status != robo->prev_status)) { + for (phy = 0; phy < MAX_NO_PHYS; phy++) { + if (first) { + if (!(link_status & (1 << phy))) + robo_link_down(robo, phy); + } else if ((link_status & (1 << phy)) != (robo->prev_status & (1 << phy))) { + if (!(link_status & (1 << phy))) + robo_link_down(robo, phy); + else + robo_link_up(robo, phy); + } + } + robo->prev_status = link_status; + first = 0; + } +} + +void +robo_eee_advertise_init(robo_info_t *robo) +{ + uint16 val16; + int32 phy; + + ASSERT(robo); + + val16 = 0; + robo->ops->read_reg(robo, 0x92, 0x00, &val16, sizeof(val16)); + if (val16 == 0x1f) { + robo->eee_status = TRUE; + printf("bcm_robo_enable_switch: EEE is enabled\n"); + } else { + for (phy = 0; phy < MAX_NO_PHYS; phy++) { + /* select DEVAD 7 */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x0007); + /* select register 3Ch */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, 0x003c); + /* read command */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0xc007); + /* read data */ + val16 = robo->miird(robo->h, phy, REG_MII_CLAUSE_45_CTL2); + val16 &= ~0x6; + /* select DEVAD 7 */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x0007); + /* select register 3Ch */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, 0x003c); + /* write command */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL1, 0x4007); + /* write data */ + robo->miiwr(robo->h, phy, REG_MII_CLAUSE_45_CTL2, val16); + } + robo->eee_status = FALSE; + printf("bcm_robo_enable_switch: EEE is disabled\n"); + } +} + +int +bcm_robo_flow_control(robo_info_t *robo, bool set) +{ + uint8 val8; + int ret = -1; + + /* Enable management interface access */ + if (robo->ops->enable_mgmtif) + robo->ops->enable_mgmtif(robo); + + /* Only 53125 family is supported for now */ + if (robo->devid == DEVID53125) { + /* Over ride IMP port flow control RX/TX capability */ + val8 = 0; + robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); + if (set) + val8 |= (RXTX_FLOW_CTRL_MASK << RXTX_FLOW_CTRL_SHIFT); + else + val8 &= ~(RXTX_FLOW_CTRL_MASK << RXTX_FLOW_CTRL_SHIFT); + robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); + ret = 0; + } + + /* Disable management interface access */ + if (robo->ops->disable_mgmtif) + robo->ops->disable_mgmtif(robo); + + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/ccsflash.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/ccsflash.c new file mode 100644 index 00000000000..949498d624b --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/ccsflash.c @@ -0,0 +1,707 @@ +/* + * Broadcom SiliconBackplane chipcommon serial flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: ccsflash.c 667654 2016-10-28 02:10:45Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BCMDBG +#define SFL_MSG(args) printf args +#else +#define SFL_MSG(args) +#endif /* BCMDBG */ + +/* Private global state */ +static hndsflash_t ccsflash; + +/* Prototype */ +hndsflash_t *ccsflash_init(si_t *sih); +static int ccsflash_poll(hndsflash_t *sfl, uint offset); +static int ccsflash_read(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); +static int ccsflash_write(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); +static int ccsflash_erase(hndsflash_t *sfl, uint offset); +static int ccsflash_commit(hndsflash_t *sfl, uint offset, uint len, const uchar *buf); + +/* Issue a serial flash command */ +static INLINE void +ccsflash_cmd(osl_t *osh, chipcregs_t *cc, uint opcode) +{ + W_REG(osh, &cc->flashcontrol, SFLASH_START | opcode); + while (R_REG(osh, &cc->flashcontrol) & SFLASH_BUSY); +} + +static bool firsttime = TRUE; + +/* Initialize serial flash access */ +hndsflash_t * +ccsflash_init(si_t *sih) +{ + chipcregs_t *cc; + uint32 id = 0, id2; + const char *name = ""; + osl_t *osh; + + ASSERT(sih); + + /* No sflash for NorthStar */ + if (sih->ccrev == 42) + return NULL; + + if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL) + return NULL; + + if (!firsttime && ccsflash.size != 0) + return &ccsflash; + + osh = si_osh(sih); + + bzero(&ccsflash, sizeof(ccsflash)); + ccsflash.sih = sih; + ccsflash.core = (void *)cc; + ccsflash.read = ccsflash_read; + ccsflash.write = ccsflash_write; + ccsflash.erase = ccsflash_erase; + ccsflash.commit = ccsflash_commit; + ccsflash.poll = ccsflash_poll; + + ccsflash.type = sih->cccaps & CC_CAP_FLASH_MASK; + + switch (ccsflash.type) { + case SFLASH_ST: + /* Probe for ST chips */ + name = "ST compatible"; + ccsflash_cmd(osh, cc, SFLASH_ST_DP); + W_REG(osh, &cc->flashaddress, 0); + ccsflash_cmd(osh, cc, SFLASH_ST_RES); + id = R_REG(osh, &cc->flashdata); + ccsflash.blocksize = 64 * 1024; + switch (id) { + case 0x11: + /* ST M25P20 2 Mbit Serial Flash */ + ccsflash.numblocks = 4; + break; + case 0x12: + /* ST M25P40 4 Mbit Serial Flash */ + ccsflash.numblocks = 8; + break; + case 0x13: + ccsflash_cmd(osh, cc, SFLASH_MXIC_RDID); + id = R_REG(osh, &cc->flashdata); + if (id == SFLASH_MXIC_MFID) { + /* MXIC MX25L8006E 8 Mbit Serial Flash */ + ccsflash.blocksize = 4 * 1024; + ccsflash.numblocks = 16 * 16; + } else { + /* ST M25P80 8 Mbit Serial Flash */ + ccsflash.numblocks = 16; + } + break; + case 0x14: + /* ST M25P16 16 Mbit Serial Flash */ + ccsflash.numblocks = 32; + break; + case 0x15: + /* ST M25P32 32 Mbit Serial Flash */ + ccsflash.numblocks = 64; + break; + case 0x16: + /* ST M25P64 64 Mbit Serial Flash */ + ccsflash.numblocks = 128; + break; + case 0x17: + /* ST M25FL128 128 Mbit Serial Flash */ + ccsflash.numblocks = 256; + break; + case 0x18: + /* MXIC MX25L25635F 256Mbit Serial Flash */ + ccsflash.numblocks = 512; + break; + case 0xbf: + /* All of the following flashes are SST with + * 4KB subsectors. Others should be added but + * We'll have to revamp the way we identify them + * since RES is not eough to disambiguate them. + */ + name = "SST"; + ccsflash.blocksize = 4 * 1024; + W_REG(osh, &cc->flashaddress, 1); + ccsflash_cmd(osh, cc, SFLASH_ST_RES); + id2 = R_REG(osh, &cc->flashdata); + switch (id2) { + case 1: + /* SST25WF512 512 Kbit Serial Flash */ + ccsflash.numblocks = 16; + break; + case 0x48: + /* SST25VF512 512 Kbit Serial Flash */ + ccsflash.numblocks = 16; + break; + case 2: + /* SST25WF010 1 Mbit Serial Flash */ + ccsflash.numblocks = 32; + break; + case 0x49: + /* SST25VF010 1 Mbit Serial Flash */ + ccsflash.numblocks = 32; + break; + case 3: + /* SST25WF020 2 Mbit Serial Flash */ + ccsflash.numblocks = 64; + break; + case 0x43: + /* SST25VF020 2 Mbit Serial Flash */ + ccsflash.numblocks = 64; + break; + case 4: + /* SST25WF040 4 Mbit Serial Flash */ + ccsflash.numblocks = 128; + break; + case 0x44: + /* SST25VF040 4 Mbit Serial Flash */ + ccsflash.numblocks = 128; + break; + case 0x8d: + /* SST25VF040B 4 Mbit Serial Flash */ + ccsflash.numblocks = 128; + break; + case 5: + /* SST25WF080 8 Mbit Serial Flash */ + ccsflash.numblocks = 256; + break; + case 0x8e: + /* SST25VF080B 8 Mbit Serial Flash */ + ccsflash.numblocks = 256; + break; + case 0x41: + /* SST25VF016 16 Mbit Serial Flash */ + ccsflash.numblocks = 512; + break; + case 0x4a: + /* SST25VF032 32 Mbit Serial Flash */ + ccsflash.numblocks = 1024; + break; + case 0x4b: + /* SST25VF064 64 Mbit Serial Flash */ + ccsflash.numblocks = 2048; + break; + } + break; + } + break; + + case SFLASH_AT: + /* Probe for Atmel chips */ + name = "Atmel"; + ccsflash_cmd(osh, cc, SFLASH_AT_STATUS); + id = R_REG(osh, &cc->flashdata) & 0x3c; + switch (id) { + case 0xc: + /* Atmel AT45DB011 1Mbit Serial Flash */ + ccsflash.blocksize = 256; + ccsflash.numblocks = 512; + break; + case 0x14: + /* Atmel AT45DB021 2Mbit Serial Flash */ + ccsflash.blocksize = 256; + ccsflash.numblocks = 1024; + break; + case 0x1c: + /* Atmel AT45DB041 4Mbit Serial Flash */ + ccsflash.blocksize = 256; + ccsflash.numblocks = 2048; + break; + case 0x24: + /* Atmel AT45DB081 8Mbit Serial Flash */ + ccsflash.blocksize = 256; + ccsflash.numblocks = 4096; + break; + case 0x2c: + /* Atmel AT45DB161 16Mbit Serial Flash */ + ccsflash.blocksize = 512; + ccsflash.numblocks = 4096; + break; + case 0x34: + /* Atmel AT45DB321 32Mbit Serial Flash */ + ccsflash.blocksize = 512; + ccsflash.numblocks = 8192; + break; + case 0x3c: + /* Atmel AT45DB642 64Mbit Serial Flash */ + ccsflash.blocksize = 1024; + ccsflash.numblocks = 8192; + break; + } + break; + } + + ccsflash.size = ccsflash.blocksize * ccsflash.numblocks; + ccsflash.phybase = SI_FLASH2; + ccsflash.device_id = id; + + if (ccsflash.size) { + ccsflash.base = (uint32)REG_MAP(ccsflash.phybase, ccsflash.size); + } + + if (firsttime) { + if (ccsflash.size == 0) { + printf("ERROR: Unknown flash, device_id:0x%02X\n", id); + } else { + printf("Found %s serial flash with %d %dKB blocks; total size %dMB\n", + name, ccsflash.numblocks, ccsflash.blocksize / 1024, + ccsflash.size / (1024 * 1024)); + } + } + + firsttime = FALSE; + return ccsflash.size ? &ccsflash : NULL; +} + +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ +static int +ccsflash_read(hndsflash_t *sfl, uint offset, uint len, const uchar *buf) +{ + si_t *sih = sfl->sih; + uint8 *from, *to; + int i, cnt = len; + + ASSERT(sih); + + if (!len) + return 0; + + if ((offset + len) > sfl->size) + return -22; + + if (sih->ccrev == 12) { + from = (uint8 *)OSL_UNCACHED((void *)SI_FLASH2 + offset); + } else if (sih->ccrev == 54) { + from = (uint8 *)((void *)sfl->base + offset); + } else { + from = (uint8 *)OSL_CACHED((void *)SI_FLASH2 + offset); + } + to = (uint8 *)buf; + + if ((offset + len) <= SI_FLASH_WINDOW) { + if ((len >= 4) && (offset & 3)) + cnt = 4 - (offset & 3); + else if ((len >= 4) && ((uintptr)buf & 3)) + cnt = 4 - ((uintptr)buf & 3); + + if (cnt < 4) { + for (i = 0; i < cnt; i ++) { + /* Cannot use R_REG because in bigendian that will + * xor the address and we don't want that here. + */ + *to = *from; + from ++; + to ++; + } + return cnt; + } + + while (cnt >= 4) { + *(uint32 *)to = *(uint32 *)from; + from += 4; + to += 4; + cnt -= 4; + } + } else { + osl_t *osh = si_osh(sih); + chipcregs_t *cc = (chipcregs_t *)sfl->core; + uint cmd = 0, off = offset; + + switch (sfl->device_id) { + case 0x18: + /* MXIC MX25L25635F 256Mbit Serial Flash */ + cmd = SFLASH_ST_READ4B; + break; + default: + printf("ERROR: Need to support 4BYTE address command\n"); + return -1; + break; + } + + while (cnt) { + W_REG(osh, &cc->flashaddress, off); + ccsflash_cmd(osh, cc, cmd); + *to = R_REG(osh, &cc->flashdata) & 0xff; + off++; + to++; + cnt--; + } + } + + return (len - cnt); +} + +/* Poll for command completion. Returns zero when complete. */ +static int +ccsflash_poll(hndsflash_t *sfl, uint offset) +{ + si_t *sih = sfl->sih; + chipcregs_t *cc = (chipcregs_t *)sfl->core; + osl_t *osh; + + ASSERT(sih); + + osh = si_osh(sih); + + if (offset >= sfl->size) + return -22; + + switch (sfl->type) { + case SFLASH_ST: + /* Check for ST Write In Progress bit */ + ccsflash_cmd(osh, cc, SFLASH_ST_RDSR); + return R_REG(osh, &cc->flashdata) & SFLASH_ST_WIP; + case SFLASH_AT: + /* Check for Atmel Ready bit */ + ccsflash_cmd(osh, cc, SFLASH_AT_STATUS); + return !(R_REG(osh, &cc->flashdata) & SFLASH_AT_READY); + } + + return 0; +} + +/* Write len bytes starting at offset into buf. Returns number of bytes + * written. Caller should poll for completion. + */ +#define ST_RETRIES 3 + +#ifdef IL_BIGENDIAN +#ifdef BCMHND74K +#define GET_BYTE(ptr) (*(uint8 *)((uint32)(ptr) ^ 7)) +#else /* !74K, bcm33xx */ +#define GET_BYTE(ptr) (*(uint8 *)((uint32)(ptr) ^ 3)) +#endif /* BCMHND74K */ +#else /* !IL_BIGENDIAN */ +#define GET_BYTE(ptr) (*(ptr)) +#endif /* IL_BIGENDIAN */ + +static int +ccsflash_write(hndsflash_t *sfl, uint offset, uint length, const uchar *buffer) +{ + si_t *sih = sfl->sih; + chipcregs_t *cc = (chipcregs_t *)sfl->core; + uint off = offset, len = length; + const uint8 *buf = buffer; + uint8 data; + int ret = 0, ntry = 0; + uint32 page, byte, mask; + osl_t *osh; + + ASSERT(sih); + + osh = si_osh(sih); + + if (!len) + return 0; + + if ((off + len) > sfl->size) + return -22; + + switch (sfl->type) { + case SFLASH_ST: + /* Enable writes */ + ccsflash_cmd(osh, cc, SFLASH_ST_WREN); + off = offset; + len = length; + buf = buffer; + ntry++; + if (sih->ccrev >= 20) { + uint cmd = SFLASH_ST_PP; + + if ((off + len) <= SI_FLASH_WINDOW) { + cmd = SFLASH_ST_PP; + } else { + switch (sfl->device_id) { + case 0x18: + /* MXIC MX25L25635F 256Mbit Serial Flash */ + cmd = SFLASH_ST_PP4B; + break; + default: + printf("ERROR: Need to support 4BYTE address command\n"); + return -1; + break; + } + } + + W_REG(osh, &cc->flashaddress, off); + data = GET_BYTE(buf); + buf++; + W_REG(osh, &cc->flashdata, data); + /* Issue a page program with CSA bit set */ + ccsflash_cmd(osh, cc, SFLASH_ST_CSA | cmd); + ret = 1; + off++; + len--; + while (len > 0) { + if ((off & 255) == 0) { + /* Page boundary, poll droping cs and return */ + W_REG(NULL, &cc->flashcontrol, 0); + OSL_DELAY(1); + for (;;) { + int status = ccsflash_poll(sfl, off); + + if (status < 0) { + return status; + } else if ((status & SFLASH_ST_WIP) + != SFLASH_ST_WIP) { + break; + } + } + return ret; + } else { + /* Write single byte */ + data = GET_BYTE(buf); + buf++; + ccsflash_cmd(osh, cc, SFLASH_ST_CSA | data); + } + ret++; + off++; + len--; + } + /* All done, drop cs & poll */ + W_REG(NULL, &cc->flashcontrol, 0); + OSL_DELAY(1); + for (;;) { + int status = ccsflash_poll(sfl, off); + + if (status < 0) { + return status; + } else if ((status & SFLASH_ST_WIP) + != SFLASH_ST_WIP) { + break; + } + } + } else { + ret = 1; + W_REG(osh, &cc->flashaddress, off); + data = GET_BYTE(buf); + buf++; + W_REG(osh, &cc->flashdata, data); + /* Page program */ + ccsflash_cmd(osh, cc, SFLASH_ST_PP); + } + break; + case SFLASH_AT: + mask = sfl->blocksize - 1; + page = (off & ~mask) << 1; + byte = off & mask; + /* Read main memory page into buffer 1 */ + if (byte || (len < sfl->blocksize)) { + W_REG(osh, &cc->flashaddress, page); + ccsflash_cmd(osh, cc, SFLASH_AT_BUF1_LOAD); + /* 250 us for AT45DB321B */ + SPINWAIT(ccsflash_poll(sfl, off), 1000); + ASSERT(!ccsflash_poll(sfl, off)); + } + /* Write into buffer 1 */ + for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) { + W_REG(osh, &cc->flashaddress, byte++); + W_REG(osh, &cc->flashdata, *buf++); + ccsflash_cmd(osh, cc, SFLASH_AT_BUF1_WRITE); + } + /* Write buffer 1 into main memory page */ + W_REG(osh, &cc->flashaddress, page); + ccsflash_cmd(osh, cc, SFLASH_AT_BUF1_PROGRAM); + break; + } + + return ret; +} + +/* Erase a region. Returns number of bytes scheduled for erasure. + * Caller should poll for completion. + */ +static int +ccsflash_erase(hndsflash_t *sfl, uint offset) +{ + si_t *sih = sfl->sih; + chipcregs_t *cc = (chipcregs_t *)sfl->core; + osl_t *osh; + + ASSERT(sih); + + osh = si_osh(sih); + + if (offset >= sfl->size) + return -22; + + switch (sfl->type) { + case SFLASH_ST: { + uint cmd = 0, off = offset; + ccsflash_cmd(osh, cc, SFLASH_ST_WREN); + W_REG(osh, &cc->flashaddress, offset); + /* Newer flashes have "sub-sectors" which can be erased independently + * with a new command: ST_SSE. The ST_SE command erases 64KB just as + * before. + */ + if (off < SI_FLASH_WINDOW) { + if (sfl->blocksize < (64 * 1024)) + cmd = SFLASH_ST_SSE; + else + cmd = SFLASH_ST_SE; + } + else { + uint secmd = 0, ssecmd = 0; + switch (sfl->device_id) { + case 0x18: + /* MXIC MX25L25635F 256Mbit Serial Flash */ + secmd = SFLASH_ST_SE4B; + ssecmd = SFLASH_ST_SSE4B; + break; + default: + printf("ERROR: Need to support 4BYTE address command\n"); + return -1; + break; + } + + if (sfl->blocksize < (64 * 1024)) + cmd = ssecmd; + else + cmd = secmd; + } + + ccsflash_cmd(osh, cc, cmd); + return sfl->blocksize; + } + case SFLASH_AT: + W_REG(osh, &cc->flashaddress, offset << 1); + ccsflash_cmd(osh, cc, SFLASH_AT_PAGE_ERASE); + return sfl->blocksize; + } + + return 0; +} + +/* + * writes the appropriate range of flash, a NULL buf simply erases + * the region of flash + */ +static int +ccsflash_commit(hndsflash_t *sfl, uint offset, uint len, const uchar *buf) +{ + si_t *sih = sfl->sih; + uchar *block = NULL, *cur_ptr, *blk_ptr; + uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; + uint blk_offset, blk_len, copied; + int bytes, ret = 0; + osl_t *osh; + + ASSERT(sih); + + osh = si_osh(sih); + + /* Check address range */ + if (len <= 0) + return 0; + + if ((offset + len) > sfl->size) + return -1; + + blocksize = sfl->blocksize; + mask = blocksize - 1; + + /* Allocate a block of mem */ + if (!(block = MALLOC(osh, blocksize))) + return -1; + + while (len) { + /* Align offset */ + cur_offset = offset & ~mask; + cur_length = blocksize; + cur_ptr = block; + + remainder = blocksize - (offset & mask); + if (len < remainder) + cur_retlen = len; + else + cur_retlen = remainder; + + /* buf == NULL means erase only */ + if (buf) { + /* Copy existing data into holding block if necessary */ + if ((offset & mask) || (len < blocksize)) { + blk_offset = cur_offset; + blk_len = cur_length; + blk_ptr = cur_ptr; + + /* Copy entire block */ + while (blk_len) { + copied = ccsflash_read(sfl, blk_offset, blk_len, blk_ptr); + blk_offset += copied; + blk_len -= copied; + blk_ptr += copied; + } + } + + /* Copy input data into holding block */ + memcpy(cur_ptr + (offset & mask), buf, cur_retlen); + } + + /* Erase block */ + if ((ret = ccsflash_erase(sfl, (uint) cur_offset)) < 0) + goto done; + while (ccsflash_poll(sfl, (uint) cur_offset)); + + /* buf == NULL means erase only */ + if (!buf) { + offset += cur_retlen; + len -= cur_retlen; + continue; + } + + /* Write holding block */ + while (cur_length > 0) { + if ((bytes = ccsflash_write(sfl, + (uint) cur_offset, + (uint) cur_length, + (uchar *) cur_ptr)) < 0) { + ret = bytes; + goto done; + } + while (ccsflash_poll(sfl, (uint) cur_offset)); + cur_offset += bytes; + cur_length -= bytes; + cur_ptr += bytes; + } + + offset += cur_retlen; + len -= cur_retlen; + buf += cur_retlen; + } + + ret = len; +done: + if (block) + MFREE(osh, block, blocksize); + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndarm_ca9.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndarm_ca9.c new file mode 100644 index 00000000000..c1894eb61bd --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndarm_ca9.c @@ -0,0 +1,572 @@ +/* + * BCM43XX Sonics SiliconBackplane ARM core routines + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: hndarm_ca9.c 678682 2017-01-10 16:37:04Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLL_SUP_4708 0x00000001 +#define PLL_SUP_4709 0x00000002 +#define PLL_SUP_47092 0x00000004 +#define PLL_SUP_47094 0x00000008 +#define PLL_SUP_NS_ALL (PLL_SUP_4708 | PLL_SUP_4709 | PLL_SUP_47092 | PLL_SUP_47094) +#define PLL_SUP_53573 0x00000010 + +#define PLL_SUP_DDR2 0x00000001 +#define PLL_SUP_DDR3 0x00000002 + +struct arm_pll { + uint32 clk; + uint32 reg_val; + uint32 flag; +}; + +struct arm_ca7_pll { + uint32 cpu; + uint32 cci; + uint32 nic; + uint32 pll_ctrl_1; /* ndiv_nfrac */ + uint32 pll_ctrl_2; /* mdiv */ + uint32 clkratioarm; + uint32 clkratiocci; +}; + +struct ddr_clk { + uint32 clk; + uint32 pll_ctrl_1; + uint32 pll_ctrl_2; + uint32 type_flag; + uint32 flag; +}; + +static struct arm_pll arm_pll_table[] = { + { 600, 0x1003001, PLL_SUP_NS_ALL}, + { 800, 0x1004001, PLL_SUP_NS_ALL}, + { 900, 0, PLL_SUP_53573}, + { 1000, 0x1005001, PLL_SUP_4709 | PLL_SUP_47092 | PLL_SUP_47094}, + { 1200, 0x1006001, PLL_SUP_47094}, + { 1400, 0x1007001, PLL_SUP_47094}, + {0} +}; + +static struct arm_ca7_pll arm_pll_ca7_table[] = { + {600, 300, 150, 0x01680000, 0x010c0603, 1, 1}, + {0} +}; + +static struct ddr_clk ddr_clock_pll_table[] = { + { 286, 0, 0, PLL_SUP_DDR2, PLL_SUP_53573}, + { 318, 0, 0, PLL_SUP_DDR2 | PLL_SUP_DDR3, PLL_SUP_53573}, + { 333, 0x17800000, 0x1e0f1219, PLL_SUP_DDR2 | PLL_SUP_DDR3, PLL_SUP_NS_ALL}, + { 358, 0, 0, PLL_SUP_DDR2 | PLL_SUP_DDR3, PLL_SUP_53573}, + { 389, 0x18c00000, 0x23121219, PLL_SUP_DDR2 | PLL_SUP_DDR3, PLL_SUP_NS_ALL}, + { 392, 0, 0, PLL_SUP_DDR2 | PLL_SUP_DDR3, PLL_SUP_53573}, + { 400, 0x18000000, 0x20101019, PLL_SUP_DDR2 | PLL_SUP_DDR3, PLL_SUP_NS_ALL}, + { 533, 0x18000000, 0x20100c19, PLL_SUP_DDR3, PLL_SUP_NS_ALL | PLL_SUP_53573}, + { 666, 0x17800000, 0x1e0f0919, PLL_SUP_DDR3, PLL_SUP_4709 | PLL_SUP_47094}, + { 775, 0x17c00000, 0x20100819, PLL_SUP_DDR3, PLL_SUP_4709 | PLL_SUP_47094}, + { 800, 0x18000000, 0x20100819, PLL_SUP_DDR3, PLL_SUP_4709 | PLL_SUP_47094}, + {0} +}; + +uint +BCMINITFN(si_irq)(si_t *sih) +{ + return 0; +} + +/* + * Initializes clocks and interrupts. SB and NVRAM access must be + * initialized prior to calling. + */ +void +BCMATTACHFN(si_arm_init)(si_t *sih) +{ + return; +} + +uint32 +BCMINITFN(si_cpu_clock)(si_t *sih) +{ + uint32 val; + osl_t *osh; + osh = si_osh(sih); + + if (BCM4707_CHIP(CHIPID(sih->chip))) { + /* Return 100 MHz if we are in default value policy 2 */ + val = (uint32)R_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_FREQ); + if ((val & 0x7070707) == 0x2020202) + return 100000000; + + val = (uint32)R_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA); + val = (val >> 8) & 0x2ff; + val = (val * 25 * 1000000) / 2; + + return val; + } + +#ifdef _CFE_ /* only compile tailed 53573 block in cfe, to avoid impact 4708 cfez size \ + */ + if (PMUCTL_ENAB(sih)) +#endif + if (BCM53573_CHIP(CHIPID(sih->chip))) { + pmuregs_t *pmu; + uint origidx; + uint32 fvco, pdiv, pll_ctrl_20, mdiv, ndiv_nfrac, clkout, r_high, r_low; + uint32 xtal_freq = si_alp_clock(sih); + + origidx = si_coreidx(sih); + pmu = si_setcore(sih, PMU_CORE_ID, 0); + ASSERT(pmu != NULL); + + /* Read mdiv, pdiv from pllcontrol[13] */ + W_REG(osh, &pmu->pllcontrol_addr, 13); + mdiv = R_REG(osh, &pmu->pllcontrol_data) & 0xff; + ASSERT(mdiv); + pdiv = (R_REG(osh, &pmu->pllcontrol_data) >> 24) & 0x7; + ASSERT(pdiv); + + /* Read ndiv[29:20], ndiv_frac[19:0] from pllcontrol[14] */ + W_REG(osh, &pmu->pllcontrol_addr, 14); + ndiv_nfrac = R_REG(osh, &pmu->pllcontrol_data) & 0x3fffffff; + + /* Read pll_ctrl_20 from pllcontrol[15] */ + W_REG(osh, &pmu->pllcontrol_addr, 15); + pll_ctrl_20 = 1 << ((R_REG(osh, &pmu->pllcontrol_data) >> 20) & 0x1); + + math_uint64_multiple_add(&r_high, &r_low, ndiv_nfrac, (xtal_freq * pll_ctrl_20), 0); + math_uint64_right_shift(&fvco, r_high, r_low, 20); + + clkout = (fvco / pdiv)/ mdiv; + + /* Return to original core */ + si_setcoreidx(sih, origidx); + + return clkout; + } + return si_clock(sih); +} + +uint32 +BCMINITFN(si_mem_clock)(si_t *sih) +{ + osl_t *osh; + uint idx; + chipcommonbregs_t *chipcb; + uint32 control1, control2, val; + + osh = si_osh(sih); + + if (BCM4707_CHIP(CHIPID(sih->chip))) { + chipcb = si_setcore(sih, NS_CCB_CORE_ID, 0); + if (chipcb) { + control1 = R_REG(osh, &chipcb->cru_lcpll_control1); + control2 = R_REG(osh, &chipcb->cru_lcpll_control2); + for (idx = 0; ddr_clock_pll_table[idx].clk != 0; idx++) { + if ((control1 == ddr_clock_pll_table[idx].pll_ctrl_1) && + (control2 == ddr_clock_pll_table[idx].pll_ctrl_2)) { + val = ddr_clock_pll_table[idx].clk; + return (val * 1000000); + } + } + } + + } + +#ifdef _CFE_ /* only compile tailed 53573 block in cfe, to avoid impact 4708 cfez size \ + */ + if (PMUCTL_ENAB(sih)) +#endif + if (BCM53573_CHIP(CHIPID(sih->chip))) { + pmuregs_t *pmu; + uint origidx; + uint32 fvco, pdiv, pll_ctrl_20, mdiv, ndiv_nfrac, clkout, r_high, r_low; + uint32 xtal_freq = si_alp_clock(sih); + + origidx = si_coreidx(sih); + pmu = si_setcore(sih, PMU_CORE_ID, 0); + ASSERT(pmu != NULL); + + /* Read mdiv from pllcontrol[25] */ + W_REG(osh, &pmu->pllcontrol_addr, 25); + mdiv = (R_REG(osh, &pmu->pllcontrol_data) >> 16) & 0xff; + ASSERT(mdiv); + + /* Read pdiv[18:16], ndiv[29:20], ndiv_frac[31] from pllcontrol[26] */ + W_REG(osh, &pmu->pllcontrol_addr, 26); + pdiv = (R_REG(osh, &pmu->pllcontrol_data) >> 16) & 0x7; + ndiv_nfrac = R_REG(osh, &pmu->pllcontrol_data) & 0x3ff00000; + ndiv_nfrac |= (R_REG(osh, &pmu->pllcontrol_data) & 0x80000000)? 1: 0; + ASSERT(pdiv); + + /* Read ndiv_frac[19:1] from pllcontrol[27] */ + W_REG(osh, &pmu->pllcontrol_addr, 27); + ndiv_nfrac |= ((R_REG(osh, &pmu->pllcontrol_data) << 1) & 0xffffe); + + /* Read pll_ctrl_20 from pllcontrol[28] */ + W_REG(osh, &pmu->pllcontrol_addr, 28); + pll_ctrl_20 = 1 << ((R_REG(osh, &pmu->pllcontrol_data) >> 20) & 0x1); + + math_uint64_multiple_add(&r_high, &r_low, ndiv_nfrac, (xtal_freq * pll_ctrl_20), 0); + math_uint64_right_shift(&fvco, r_high, r_low, 20); + + clkout = (fvco / pdiv)/ mdiv; + + /* Return to original core */ + si_setcoreidx(sih, origidx); + + return clkout; + } + return si_clock(sih); +} + +bool +BCMINITFN(si_arm_setclock)(si_t *sih, uint32 armclock, uint32 ddrclock, + uint32 axi_cciclock, uint32 nicclock) +{ + osl_t *osh; + uint32 val; + bool ret = TRUE; + int idx; + int bootdev; + uint32 *ddrclk; + osh = si_osh(sih); + + if (BCM4707_CHIP(CHIPID(sih->chip))) { + uint32 platform_flag = 0, ddr_flag = 0; + void *regs = (void *)si_setcore(sih, NS_DDR23_CORE_ID, 0); + if (regs) { + ddr_flag = ((si_core_sflags(sih, 0, 0) & DDR_TYPE_MASK) + == DDR_STAT_DDR3)? PLL_SUP_DDR3 : PLL_SUP_DDR2; + } + + switch (sih->chippkg) { + case BCM4708_PKG_ID: + if (CHIPID(sih->chip) == BCM47094_CHIP_ID) { + platform_flag = PLL_SUP_47092; + } else { + platform_flag = PLL_SUP_4708; + } + break; + case BCM4709_PKG_ID: + if (CHIPID(sih->chip) == BCM47094_CHIP_ID) { + platform_flag = PLL_SUP_47094; + } else { + platform_flag = PLL_SUP_4709; + } + break; + } + + /* Check CPU CLK table */ + for (idx = 0; arm_pll_table[idx].clk != 0; idx++) { + if ((arm_pll_table[idx].flag & platform_flag) == 0) + arm_pll_table[idx].clk = 0; + } + + /* Check DDR CLK table */ + for (idx = 0; ddr_clock_pll_table[idx].clk != 0; idx++) { + if ((ddr_clock_pll_table[idx].type_flag & ddr_flag) == 0 || + (ddr_clock_pll_table[idx].flag & platform_flag) == 0) { + ddr_clock_pll_table[idx].clk = 0; + break; + } + } + + /* Check DDR clock */ + if (ddrclock && si_mem_clock(sih) != ddrclock) { + ddrclock /= 1000000; + for (idx = 0; ddr_clock_pll_table[idx].clk != 0; idx ++) { + if (ddrclock == ddr_clock_pll_table[idx].clk) + break; + } + if (ddr_clock_pll_table[idx].clk != 0) { + ddrclk = (uint32 *)(0x1000 + BISZ_OFFSET - 4); + *ddrclk = ddrclock; + bootdev = soc_boot_dev((void *)sih); + if (bootdev == SOC_BOOTDEV_NANDFLASH) { + __asm__ __volatile__("ldr\tpc,=0x1c000000\n\t"); + } else if (bootdev == SOC_BOOTDEV_SFLASH) { + __asm__ __volatile__("ldr\tpc,=0x1e000000\n\t"); + } + } + } + + /* Set CPU clock */ + armclock /= 1000000; + + /* The password */ + W_REG(osh, (uint32 *)IHOST_PROC_CLK_WR_ACCESS, 0xa5a501); + + /* Bypass ARM clock and run on the default sysclk */ + W_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_FREQ, 0x82020202); + + val = (1 << IHOST_PROC_CLK_POLICY_CTL__GO) | + (1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_CTL, val); + + do { + val = R_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_CTL); + if ((val & (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) == 0) + break; + } while (1); + + /* Now it is safe to program the ARM PLL. + * ndiv_int + */ + for (idx = 0; arm_pll_table[idx].clk != 0; idx++) { + if (armclock <= arm_pll_table[idx].clk) + break; + } + if (arm_pll_table[idx].clk == 0) { + ret = FALSE; + goto done; + } + val = arm_pll_table[idx].reg_val; + W_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA, val); + + do { + val = (uint32)R_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA); + if (val & (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK)) + break; + } while (1); + + val |= (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA, val); + + W_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_FREQ, 0x87070707); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_CORE0_CLKGATE, 0x00010303); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_CORE1_CLKGATE, 0x00000303); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_ARM_SWITCH_CLKGATE, 0x00010303); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_ARM_PERIPH_CLKGATE, 0x00010303); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_APB0_CLKGATE, 0x00010303); + + val = (1 << IHOST_PROC_CLK_POLICY_CTL__GO) | + (1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC); + W_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_CTL, val); + + do { + val = R_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_CTL); + if ((val & (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) == 0) + break; + } while (1); + } + +#ifdef _CFE_ /* only compile tailed 53573 block in cfe, to avoid impact 4708 cfez size \ + */ + if (PMUCTL_ENAB(sih)) +#endif /* _CFE */ + if (BCM53573_CHIP(CHIPID(sih->chip))) { + /* Check DDR clock */ + ddrclock /= 1000000; + + if (ddrclock && (si_mem_clock(sih)/1000000 != ddrclock)) { + uint32 ddr_flag = 0; + gciregs_t *gci = (gciregs_t *)si_setcore(sih, GCI_CORE_ID, 0); + + /* check strap_ddr_type: 0: ddr2, 1: ddr3 */ + W_REG(osh, (uint32 *)&gci->gci_indirect_addr, 7); + ddr_flag = ((R_REG(osh, &gci->gci_chipsts) & SI_BCM53573_DDRTYPE_MASK) + == SI_BCM53573_DDRTYPE_DDR3)? PLL_SUP_DDR3 : PLL_SUP_DDR2; + + for (idx = 0; ddr_clock_pll_table[idx].clk != 0; idx ++) { + if (ddrclock == ddr_clock_pll_table[idx].clk && + ddr_clock_pll_table[idx].type_flag & ddr_flag && + ddr_clock_pll_table[idx].flag & PLL_SUP_53573) + break; + } + + if (ddr_clock_pll_table[idx].clk != 0) { + ddrclk = (uint32 *)(0x1000 + BISZ_OFFSET - 4); + *ddrclk = ddrclock; + bootdev = soc_boot_dev((void *)sih); + if (bootdev == SOC_BOOTDEV_SFLASH) { + __asm__ __volatile__("ldr\tpc,=0x1c000000\n\t"); + } else if (bootdev == SOC_BOOTDEV_NANDFLASH) { + __asm__ __volatile__("ldr\tpc,=0x30000000\n\t"); + } + } + } + + /* 53573B0 have issue when it change CPU clock frequency. bypass it */ + if (CHIPREV(sih->chiprev) >= 2) { + goto done; + } + + /* Set CPU clock */ + armclock /= 1000000; + axi_cciclock /= 1000000; + nicclock /= 1000000; + + if ((armclock && (si_cpu_clock(sih)/1000000 != armclock)) || + (axi_cciclock != 0 && nicclock != 0)) { + chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX); + pmuregs_t *pmu = (pmuregs_t *)si_setcore(sih, PMU_CORE_ID, 0); + ca7regs_t *ca7 = (ca7regs_t*)si_setcore(sih, ARMCA7_CORE_ID, 0); + + for (idx = 0; arm_pll_ca7_table[idx].cpu != 0; idx ++) { + if (armclock == arm_pll_ca7_table[idx].cpu && + axi_cciclock == arm_pll_ca7_table[idx].cci && + nicclock == arm_pll_ca7_table[idx].nic) { + printf("set CPU:CCI:NIC to %d:%d:%d \n", armclock, + axi_cciclock, nicclock); + break; + } + } + + if (arm_pll_ca7_table[idx].cpu != 0) { + /* Set CPU:CCI:NICclock ratio to 2:2:1 */ + AND_REG(osh, (uint32 *)&ca7->corecontrol, ~(0x7<<9)); + /* Set CPU:CCI:NICclock ratio to 1:1:1 */ + AND_REG(osh, (uint32 *)&ca7->corecontrol, ~(0x3<<12)); + + /* change Fvco */ + W_REG(osh, (uint32 *)&pmu->pllcontrol_addr, 0xe); + W_REG(osh, (uint32 *)&pmu->pllcontrol_data, + arm_pll_ca7_table[idx].pll_ctrl_1); + + /* change 3 channel mdiv */ + W_REG(osh, (uint32 *)&pmu->pllcontrol_addr, 0xd); + W_REG(osh, (uint32 *)&pmu->pllcontrol_data, + arm_pll_ca7_table[idx].pll_ctrl_2); + + /* clear load_en_ch bits */ + W_REG(osh, (uint32 *)&pmu->pllcontrol_addr, 0xc); + AND_REG(osh, (uint32 *)&pmu->pllcontrol_data, ~0x7000); + + /* set PLL control update bit */ + OR_REG(osh, (uint32 *)&pmu->pmucontrol, 0x400); + /* wait until CPU PLL being locked */ + do { + val = R_REG(osh, (uint32 *)&cc->chipstatus); + if (val & SI_BCM53573_LOCKED_CPUPLL) + break; + } while (1); + + /* set load_en_ch bits */ + W_REG(osh, (uint32 *)&pmu->pllcontrol_addr, 0xc); + OR_REG(osh, (uint32 *)&pmu->pllcontrol_data, 0x7000); + + /* set PLL control update bit */ + OR_REG(osh, (uint32 *)&pmu->pmucontrol, 0x400); + /* wait until CPU PLL being locked */ + do { + val = R_REG(osh, (uint32 *)&cc->chipstatus); + if (val & SI_BCM53573_LOCKED_CPUPLL) + break; + } while (1); + + /* clear load_en_ch bits */ + W_REG(osh, (uint32 *)&pmu->pllcontrol_addr, 0xc); + AND_REG(osh, (uint32 *)&pmu->pllcontrol_data, ~0x7000); + + /* set PLL control update bit */ + OR_REG(osh, (uint32 *)&pmu->pmucontrol, 0x400); + /* wait until CPU PLL being locked */ + do { + val = R_REG(osh, (uint32 *)&cc->chipstatus); + if (val & SI_BCM53573_LOCKED_CPUPLL) + break; + } while (1); + + /* Set CCI:NIC clock ratio */ + OR_REG(osh, (uint32 *)&ca7->corecontrol, + arm_pll_ca7_table[idx].clkratiocci << 12); + + /* Set CPU:CCI clock ratio */ + OR_REG(osh, (uint32 *)&ca7->corecontrol, + arm_pll_ca7_table[idx].clkratioarm << 9); + } + } + } +done: + return (ret); +} + +void si_mem_setclock(si_t *sih, uint32 ddrclock) +{ + osl_t *osh; + chipcommonbregs_t *chipcb; + uint32 val; + int idx; + + if (BCM4707_CHIP(CHIPID(sih->chip))) { + for (idx = 0; ddr_clock_pll_table[idx].clk != 0; idx++) { + if (ddr_clock_pll_table[idx].clk == ddrclock) + break; + } + if (ddr_clock_pll_table[idx].clk == 0) + return; + + osh = si_osh(sih); + chipcb = (chipcommonbregs_t *)si_setcore(sih, NS_CCB_CORE_ID, 0); + if (chipcb) { + val = 0xea68; + W_REG(osh, &chipcb->cru_clkset_key, val); + val = R_REG(osh, &chipcb->cru_lcpll_control1); + val &= ~0x0ff00000; + val |= (ddr_clock_pll_table[idx].pll_ctrl_1 & 0x0ff00000); + W_REG(osh, &chipcb->cru_lcpll_control1, val); + + val = R_REG(osh, &chipcb->cru_lcpll_control2); + val &= ~0xffffff00; + val |= (ddr_clock_pll_table[idx].pll_ctrl_2 & 0xffffff00); + W_REG(osh, &chipcb->cru_lcpll_control2, val); + /* Enable change */ + val = R_REG(osh, &chipcb->cru_lcpll_control0); + val |= 0x7; + W_REG(osh, &chipcb->cru_lcpll_control0, val); + val &= ~0x7; + W_REG(osh, &chipcb->cru_lcpll_control0, val); + val = 0; + W_REG(osh, &chipcb->cru_clkset_key, val); + } + } + if (BCM53573_CHIP(CHIPID(sih->chip))) { + } +} + +/* Start chipc watchdog timer and wait till reset */ +void +hnd_cpu_reset(si_t *sih) +{ + si_watchdog(sih, 1); + while (1); +} + +void +hnd_cpu_jumpto(void *addr) +{ + void (*jumpto)(void) = addr; + + (jumpto)(); +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndnand.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndnand.c new file mode 100644 index 00000000000..6b79db8f143 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndnand.c @@ -0,0 +1,322 @@ +/* + * Broadcom chipcommon NAND flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: hndnand.c 596126 2015-10-29 19:53:48Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Private global state */ +static hndnand_t *hndnand = NULL; + +extern hndnand_t *nflash_init(si_t *sih); +extern hndnand_t *nandcore_init(si_t *sih); +#ifdef __mips__ +#define nandcore_enable(sih, enable) do {} while (0) +#else +extern void nandcore_enable(si_t *sih, int enable); +#endif + +/* Initialize nand flash access */ +hndnand_t * +hndnand_init(si_t *sih) +{ + uint32 origidx; + + ASSERT(sih); + + /* Already initialized ? */ + if (hndnand) + return hndnand; + + origidx = si_coreidx(sih); + +#ifdef __mips__ + if (!hndnand) + hndnand = nflash_init(sih); +#endif +#ifdef __ARM_ARCH_7A__ + if (!hndnand) { + nandcore_enable(sih, 1); + hndnand = nandcore_init(sih); + nandcore_enable(sih, 0); + } +#endif + + si_setcoreidx(sih, origidx); + return hndnand; +} + +void +hndnand_enable(hndnand_t *nfl, int enable) +{ + ASSERT(nfl); + ASSERT(nfl->sih); + + if (nfl->enable) { + nandcore_enable(nfl->sih, 1); + /* Should spinlock here */ + (nfl->enable)(nfl, enable); + nandcore_enable(nfl->sih, 0); + } + + return; +} + +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ +int +hndnand_read(hndnand_t *nfl, uint64 offset, uint len, uchar *buf) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->read); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->read)(nfl, offset, len, buf); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +/* Write len bytes starting at offset into buf. Returns number of bytes + * written. + */ +int +hndnand_write(hndnand_t *nfl, uint64 offset, uint len, const uchar *buf) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->write); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->write)(nfl, offset, len, buf); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +/* Erase a region. Returns number of bytes scheduled for erasure. + * Caller should poll for completion. + */ +int +hndnand_erase(hndnand_t *nfl, uint64 offset) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->erase); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->erase)(nfl, offset); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_checkbadb(hndnand_t *nfl, uint64 offset) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->checkbadb); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->checkbadb)(nfl, offset); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_mark_badb(hndnand_t *nfl, uint64 offset) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->markbadb); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->markbadb)(nfl, offset); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +#ifndef _CFE_ +int +hndnand_dev_ready(hndnand_t *nfl) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->dev_ready); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->dev_ready)(nfl); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_select_chip(hndnand_t *nfl, int chip) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->select_chip); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->select_chip)(nfl, chip); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int hndnand_cmdfunc(hndnand_t *nfl, uint64 addr, int cmd) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->cmdfunc); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->cmdfunc)(nfl, addr, cmd); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_waitfunc(hndnand_t *nfl, int *status) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->waitfunc); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->waitfunc)(nfl, status); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_read_oob(hndnand_t *nfl, uint64 addr, uint8 *oob) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->read_oob); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->read_oob)(nfl, addr, oob); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_write_oob(hndnand_t *nfl, uint64 addr, uint8 *oob) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->write_oob); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->write_oob)(nfl, addr, oob); + nandcore_enable(nfl->sih, 0); + + return ret; +} +int +hndnand_read_page(hndnand_t *nfl, uint64 addr, uint8 *buf, uint8 *oob, bool ecc, + uint32 *herr, uint32 *serr) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->read_page); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->read_page)(nfl, addr, buf, oob, ecc, herr, serr); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_write_page(hndnand_t *nfl, uint64 addr, const uint8 *buf, uint8 *oob, bool ecc) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->write_page); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->write_page)(nfl, addr, buf, oob, ecc); + nandcore_enable(nfl->sih, 0); + + return ret; +} + +int +hndnand_cmd_read_byte(hndnand_t *nfl, int cmd, int arg) +{ + int ret; + + ASSERT(nfl); + ASSERT(nfl->cmd_read_byte); + ASSERT(nfl->sih); + + nandcore_enable(nfl->sih, 1); + ret = (nfl->cmd_read_byte)(nfl, cmd, arg); + nandcore_enable(nfl->sih, 0); + + return ret; +} +#endif /* _CFE_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndsflash.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndsflash.c new file mode 100644 index 00000000000..0e98a3f35cc --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/hndsflash.c @@ -0,0 +1,129 @@ +/* + * Broadcom chipcommon NAND flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: hndsflash.c 596126 2015-10-29 19:53:48Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Private global state */ +static hndsflash_t *hndsflash; + +hndsflash_t *ccsflash_init(si_t *sih); +hndsflash_t *spiflash_init(si_t *sih); + +/* Initialize nand flash access */ +hndsflash_t * +hndsflash_init(si_t *sih) +{ + uint32 origidx; + + ASSERT(sih); + + /* Already initialized ? */ + if (hndsflash) + return hndsflash; + + /* spin lock here */ + origidx = si_coreidx(sih); + +#ifdef __mips__ + if (!hndsflash) + hndsflash = ccsflash_init(sih); +#endif /* __mips__ */ +#ifdef __ARM_ARCH_7A__ + if (!hndsflash) { + /* 4708 (Northstar series) */ + if (sih->ccrev == 42) + hndsflash = spiflash_init(sih); + /* 53573/47189 series */ + else if (sih->ccrev == 54) + hndsflash = ccsflash_init(sih); + } +#endif /* __ARM_ARCH_7A__ */ + + si_setcoreidx(sih, origidx); + return hndsflash; +} + +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ +int +hndsflash_read(hndsflash_t *sfl, uint offset, uint len, const uchar *buf) +{ + ASSERT(sfl); + ASSERT(sfl->read); + + return (sfl->read)(sfl, offset, len, buf); +} + +/* Write len bytes starting at offset into buf. Returns number of bytes + * written. + */ +int +hndsflash_write(hndsflash_t *sfl, uint offset, uint len, const uchar *buf) +{ + ASSERT(sfl); + ASSERT(sfl->write); + + return (sfl->write)(sfl, offset, len, (const uchar *)buf); +} + +/* Erase a region. Returns number of bytes scheduled for erasure. + * Caller should poll for completion. + */ +int +hndsflash_erase(hndsflash_t *sfl, uint offset) +{ + ASSERT(sfl); + ASSERT(sfl->erase); + + return (sfl->erase)(sfl, offset); +} + +/* + * writes the appropriate range of flash, a NULL buf simply erases + * the region of flash + */ +int hndsflash_commit(hndsflash_t *sfl, uint offset, uint len, const uchar *buf) +{ + ASSERT(sfl); + ASSERT(sfl->commit); + + return (sfl->commit)(sfl, offset, len, (const uchar *)buf); +} + +/* Poll for command completion. Returns zero when complete. */ +int hndsflash_poll(hndsflash_t *sfl, uint offset) +{ + ASSERT(sfl); + + if (!sfl->poll) + return 0; + + return (sfl->poll)(sfl, offset); +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/nflash.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/nflash.c new file mode 100644 index 00000000000..439816d9870 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/nflash.c @@ -0,0 +1,579 @@ +/* + * Broadcom chipcommon NAND flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: nflash.c 667654 2016-10-28 02:10:45Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BCMDBG +#define NFL_MSG(args) printf args +#else +#define NFL_MSG(args) +#endif /* BCMDBG */ + +#define NF_RETRIES 1000000 + +#define NF_SMALL_BADBLOCK_POS 5 +#define NF_LARGE_BADBLOCK_POS 0 + +/* Private global state */ +static hndnand_t nflash; + +/* Prototype */ +static int nflash_poll(si_t *sih, chipcregs_t *cc); +static int nflash_readst(si_t *sih, chipcregs_t *cc, uint8 *status); + +hndnand_t *nflash_init(si_t *sih); +static void nflash_enable(hndnand_t *nfl, int enable); +static int nflash_read(hndnand_t *nfl, uint64 offset, uint len, uchar *buf); +static int nflash_write(hndnand_t *nfl, uint64 offset, uint len, const uchar *buf); +static int nflash_erase(hndnand_t *nfl, uint64 offset); +static int nflash_checkbadb(hndnand_t *nfl, uint64 offset); +static int nflash_mark_badb(hndnand_t *nfl, uint64 offset); + +static void +nflash_enable(hndnand_t *nfl, int enable) +{ + si_t *sih = nfl->sih; + + if (sih->ccrev == 38) { + /* BCM5357 NAND boot */ + if ((sih->chipst & (1 << 4)) != 0) + return; + + if (enable) + si_pmu_chipcontrol(sih, 1, CCTRL5357_NFLASH, CCTRL5357_NFLASH); + else + si_pmu_chipcontrol(sih, 1, CCTRL5357_NFLASH, 0); + } +} + +/* Issue a nand flash command */ +static INLINE void +nflash_cmd(osl_t *osh, chipcregs_t *cc, uint opcode) +{ + W_REG(osh, &cc->nand_cmd_start, opcode); + /* read after write to flush the command */ + R_REG(osh, &cc->nand_cmd_start); +} + +static bool firsttime = TRUE; + +static char * +nflash_check_id(uint8 *id) +{ + char *name = NULL; + + switch (id[0]) { + case NFL_VENDOR_AMD: + name = "AMD"; + break; + case NFL_VENDOR_NUMONYX: + name = "Numonyx"; + break; + case NFL_VENDOR_MICRON: + name = "Micron"; + break; + case NFL_VENDOR_TOSHIBA: + name = "Toshiba"; + break; + case NFL_VENDOR_HYNIX: + name = "Hynix"; + break; + case NFL_VENDOR_SAMSUNG: + name = "Samsung"; + break; + case NFL_VENDOR_ESMT: + name = "Esmt"; + break; + case NFL_VENDOR_MXIC: + name = "Mxic"; + break; + case NFL_VENDOR_ZENTEL_ESMT: + name = "Zentel/Esmt"; + break; + default: + printf("No NAND flash type found\n"); + break; + } + + return name; +} + +/* Initialize nand flash access */ +hndnand_t * +nflash_init(si_t *sih) +{ + chipcregs_t *cc; + uint32 id, id2; + char *name = ""; + osl_t *osh; + int i; + uint32 ncf, val; + uint32 acc_control; + + ASSERT(sih); + + if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL) + return NULL; + + /* Only support chipcommon revision == 38 for now */ + if (sih->ccrev != 38) + return NULL; + + /* Check if nand flash is mounted */ + if ((sih->cccaps & CC_CAP_NFLASH) != CC_CAP_NFLASH) + return NULL; + + if (!firsttime && nflash.size) + return &nflash; + + osh = si_osh(sih); + bzero(&nflash, sizeof(nflash)); + + nflash.sih = sih; + nflash.core = (void *)cc; + nflash.enable = nflash_enable; + nflash.read = nflash_read; + nflash.write = nflash_write; + nflash.erase = nflash_erase; + nflash.checkbadb = nflash_checkbadb; + nflash.markbadb = nflash_mark_badb; + + nflash_enable(&nflash, 1); + nflash_cmd(osh, cc, NCMD_ID_RD); + if (nflash_poll(sih, cc) < 0) { + nflash_enable(&nflash, 0); + return NULL; + } + nflash_enable(&nflash, 0); + id = R_REG(osh, &cc->nand_devid); + id2 = R_REG(osh, &cc->nand_devid_x); + for (i = 0; i < 5; i++) { + if (i < 4) + nflash.id[i] = (id >> (8*i)) & 0xff; + else + nflash.id[i] = id2 & 0xff; + } + + name = nflash_check_id(nflash.id); + if (name == NULL) + return NULL; + nflash.type = nflash.id[0]; + + ncf = R_REG(osh, &cc->nand_config); + /* Page size (# of bytes) */ + val = (ncf & NCF_PAGE_SIZE_MASK) >> NCF_PAGE_SIZE_SHIFT; + switch (val) { + case 0: + nflash.pagesize = 512; + break; + case 1: + nflash.pagesize = (1 << 10) * 2; + break; + case 2: + nflash.pagesize = (1 << 10) * 4; + break; + case 3: + nflash.pagesize = (1 << 10) * 8; + break; + } + /* Block size (# of bytes) */ + val = (ncf & NCF_BLOCK_SIZE_MASK) >> NCF_BLOCK_SIZE_SHIFT; + switch (val) { + case 0: + nflash.blocksize = (1 << 10) * 16; + break; + case 1: + nflash.blocksize = (1 << 10) * 128; + break; + case 2: + nflash.blocksize = (1 << 10) * 8; + break; + case 3: + nflash.blocksize = (1 << 10) * 512; + break; + case 4: + nflash.blocksize = (1 << 10) * 256; + break; + default: + printf("Unknown block size\n"); + return NULL; + } + /* NAND flash size in MBytes */ + val = (ncf & NCF_DEVICE_SIZE_MASK) >> NCF_DEVICE_SIZE_SHIFT; + if (val == 0) { + printf("Unknown flash size\n"); + return NULL; + } + nflash.size = (1 << (val - 1)) * 8; + + /* More attribues for ECC functions */ + acc_control = R_REG(osh, &cc->nand_acc_control); + nflash.ecclevel = (acc_control & NAC_ECC_LEVEL_MASK) >> NAC_ECC_LEVEL_SHIFT; + nflash.ecclevel0 = (acc_control & NAC_ECC_LEVEL0_MASK) >> NAC_ECC_LEVEL0_SHIFT; + /* make sure that block-0 and block-n use the same ECC level */ + if (nflash.ecclevel != nflash.ecclevel0) { + acc_control &= ~(NAC_ECC_LEVEL_MASK | NAC_ECC_LEVEL0_MASK); + acc_control |= + (nflash.ecclevel0 << NAC_ECC_LEVEL0_SHIFT) | + (nflash.ecclevel0 << NAC_ECC_LEVEL_SHIFT); + W_REG(osh, &cc->nand_acc_control, acc_control); + nflash.ecclevel = nflash.ecclevel0; + } + nflash.phybase = SI_FLASH1; + + nflash.numblocks = (nflash.size * (1 << 10)) / (nflash.blocksize >> 10); + if (firsttime) + printf("Found a %s NAND flash with %uB pages or %dKB blocks; total size %dMB\n", + name, nflash.pagesize, (nflash.blocksize >> 10), nflash.size); + firsttime = FALSE; + return nflash.size ? &nflash : NULL; +} + +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ +static int +nflash_read(hndnand_t *nfl, uint64 offset, uint len, uchar *buf) +{ + si_t *sih = nfl->sih; + chipcregs_t *cc = (chipcregs_t *)nfl->core; + uint32 mask; + osl_t *osh; + int i; + uint32 *to; + uint32 val; + uint res; + + ASSERT(sih); + mask = NFL_SECTOR_SIZE - 1; + if ((offset & mask) != 0 || (len & mask) != 0) + return 0; + if ((((offset + len) >> 20) > nflash.size) || + ((((offset + len) >> 20) == nflash.size) && + (((offset + len) & ((1 << 20) - 1)) != 0))) + return 0; + osh = si_osh(sih); + to = (uint32 *)buf; + res = len; + + nflash_enable(nfl, 1); + while (res > 0) { + W_REG(osh, &cc->nand_cmd_addr, offset); + nflash_cmd(osh, cc, NCMD_PAGE_RD); + if (nflash_poll(sih, cc) < 0) + break; + if (((val = R_REG(osh, &cc->nand_intfc_status)) & NIST_CACHE_VALID) == 0) + break; + W_REG(osh, &cc->nand_cache_addr, 0); + for (i = 0; i < NFL_SECTOR_SIZE; i += 4, to++) { + *to = R_REG(osh, &cc->nand_cache_data); + } + + res -= NFL_SECTOR_SIZE; + offset += NFL_SECTOR_SIZE; + } + nflash_enable(nfl, 0); + + return (len - res); +} + +/* Poll for command completion. Returns zero when complete. */ +static int +nflash_poll(si_t *sih, chipcregs_t *cc) +{ + osl_t *osh; + int i; + uint32 pollmask; + + ASSERT(sih); + osh = si_osh(sih); + + pollmask = NIST_CTRL_READY|NIST_FLASH_READY; + for (i = 0; i < NF_RETRIES; i++) { + if ((R_REG(osh, &cc->nand_intfc_status) & pollmask) == pollmask) { + return 0; + } + } + + printf("nflash_poll: not ready\n"); + return -1; +} + +/* Write len bytes starting at offset into buf. Returns number of bytes + * written. + */ +static int +nflash_write(hndnand_t *nfl, uint64 offset, uint len, const uchar *buf) +{ + si_t *sih = nfl->sih; + chipcregs_t *cc = (chipcregs_t *)nfl->core; + uint32 mask; + osl_t *osh; + int i; + uint32 *from; + uint res; + uint32 reg; + int ret = 0; + uint8 status; + + ASSERT(sih); + mask = nflash.pagesize - 1; + /* Check offset and length */ + if ((offset & mask) != 0 || (len & mask) != 0) + return 0; + if ((((offset + len) >> 20) > nflash.size) || + ((((offset + len) >> 20) == nflash.size) && + (((offset + len) & ((1 << 20) - 1)) != 0))) + return 0; + osh = si_osh(sih); + + from = (uint32 *)buf; + res = len; + + nflash_enable(nfl, 1); + /* disable partial page enable */ + reg = R_REG(osh, &cc->nand_acc_control); + reg &= ~NAC_PARTIAL_PAGE_EN; + W_REG(osh, &cc->nand_acc_control, reg); + + while (res > 0) { + W_REG(osh, &cc->nand_cache_addr, 0); + for (i = 0; i < nflash.pagesize; i += 4, from++) { + if (i % 512 == 0) + W_REG(osh, &cc->nand_cmd_addr, i); + W_REG(osh, &cc->nand_cache_data, *from); + } + W_REG(osh, &cc->nand_cmd_addr, offset + nflash.pagesize - 512); + nflash_cmd(osh, cc, NCMD_PAGE_PROG); + if (nflash_poll(sih, cc) < 0) + break; + + /* Check status */ + W_REG(osh, &cc->nand_cmd_start, NCMD_STATUS_RD); + if (nflash_poll(sih, cc) < 0) + break; + status = R_REG(osh, &cc->nand_intfc_status) & NIST_STATUS; + if (status & 1) { + ret = -1; + break; + } + res -= nflash.pagesize; + offset += nflash.pagesize; + } + + nflash_enable(nfl, 0); + if (ret) + return ret; + + return (len - res); +} + +/* Erase a region. Returns number of bytes scheduled for erasure. + * Caller should poll for completion. + */ +static int +nflash_erase(hndnand_t *nfl, uint64 offset) +{ + si_t *sih = nfl->sih; + chipcregs_t *cc = (chipcregs_t *)nfl->core; + osl_t *osh; + int ret = 0; + uint8 status = 0; + + ASSERT(sih); + + osh = si_osh(sih); + if ((offset >> 20) >= nflash.size) + return -1; + if ((offset & (nflash.blocksize - 1)) != 0) { + return -1; + } + + nflash_enable(nfl, 1); + W_REG(osh, &cc->nand_cmd_addr, offset); + nflash_cmd(osh, cc, NCMD_BLOCK_ERASE); + if (nflash_poll(sih, cc) < 0) { + ret = -1; + goto err; + } + /* Check status */ + W_REG(osh, &cc->nand_cmd_start, NCMD_STATUS_RD); + if (nflash_poll(sih, cc) < 0) { + ret = -1; + goto err; + } + status = R_REG(osh, &cc->nand_intfc_status) & NIST_STATUS; + if (status & 1) + ret = -1; +err: + nflash_enable(nfl, 0); + + return ret; +} + +static int +nflash_checkbadb(hndnand_t *nfl, uint64 offset) +{ + si_t *sih = nfl->sih; + chipcregs_t *cc = (chipcregs_t *)nfl->core; + osl_t *osh; + int i; + uint off; + uint32 nand_intfc_status; + int ret = 0; + + ASSERT(sih); + + osh = si_osh(sih); + if ((offset >> 20) >= nflash.size) + return -1; + if ((offset & (nflash.blocksize - 1)) != 0) { + return -1; + } + + nflash_enable(nfl, 1); + for (i = 0; i < 2; i++) { + off = offset + (nflash.pagesize * i); + W_REG(osh, &cc->nand_cmd_addr, off); + nflash_cmd(osh, cc, NCMD_SPARE_RD); + if (nflash_poll(sih, cc) < 0) { + ret = -1; + goto err; + } + nand_intfc_status = R_REG(osh, &cc->nand_intfc_status) & NIST_SPARE_VALID; + if (nand_intfc_status != NIST_SPARE_VALID) { + ret = -1; + goto err; + } + if ((R_REG(osh, &cc->nand_spare_rd0) & 0xff) != 0xff) { + ret = -1; + goto err; + } + } +err: + nflash_enable(nfl, 0); + return ret; +} + +static int +nflash_mark_badb(hndnand_t *nfl, uint64 offset) +{ + si_t *sih = nfl->sih; + chipcregs_t *cc = (chipcregs_t *)nfl->core; + osl_t *osh; + uint off; + int i, ret = 0; + uint32 reg; + + ASSERT(sih); + + osh = si_osh(sih); + if ((offset >> 20) >= nflash.size) + return -1; + if ((offset & (nflash.blocksize - 1)) != 0) { + return -1; + } + + nflash_enable(nfl, 1); + /* Erase block */ + W_REG(osh, &cc->nand_cmd_addr, offset); + nflash_cmd(osh, cc, NCMD_BLOCK_ERASE); + if (nflash_poll(sih, cc) < 0) { + ret = -1; + goto err; + } + + /* + * Enable partial page programming and disable ECC checkbit generation + * for PROGRAM_SPARE_AREA + */ + reg = R_REG(osh, &cc->nand_acc_control); + reg |= NAC_PARTIAL_PAGE_EN; + reg &= ~NAC_WR_ECC_EN; + W_REG(osh, &cc->nand_acc_control, reg); + + for (i = 0; i < 2; i++) { + off = offset + (nflash.pagesize * i); + W_REG(osh, &cc->nand_cmd_addr, off); + + W_REG(osh, &cc->nand_spare_wr0, 0); + W_REG(osh, &cc->nand_spare_wr4, 0); + W_REG(osh, &cc->nand_spare_wr8, 0); + W_REG(osh, &cc->nand_spare_wr12, 0); + + nflash_cmd(osh, cc, NCMD_SPARE_PROG); + if (nflash_poll(sih, cc) < 0) { + ret = -1; + goto err; + } + } +err: + /* Restore the default value for spare area write registers */ + W_REG(osh, &cc->nand_spare_wr0, 0xffffffff); + W_REG(osh, &cc->nand_spare_wr4, 0xffffffff); + W_REG(osh, &cc->nand_spare_wr8, 0xffffffff); + W_REG(osh, &cc->nand_spare_wr12, 0xffffffff); + + /* + * Disable partial page programming and enable ECC checkbit generation + * for PROGRAM_SPARE_AREA + */ + reg = R_REG(osh, &cc->nand_acc_control); + reg &= ~NAC_PARTIAL_PAGE_EN; + reg |= NAC_WR_ECC_EN; + W_REG(osh, &cc->nand_acc_control, reg); + + nflash_enable(nfl, 0); + + return ret; +} + +static int +nflash_readst(si_t *sih, chipcregs_t *cc, uint8 *status) +{ + osl_t *osh; + int ret = 0; + + ASSERT(sih); + + osh = si_osh(sih); + + nflash_enable(&nflash, 1); + W_REG(osh, &cc->nand_cmd_start, NCMD_STATUS_RD); + + if (nflash_poll(sih, cc) < 0) + ret = -1; + + else + *status = (uint8)(R_REG(osh, &cc->nand_intfc_status) & NIST_STATUS); + + nflash_enable(&nflash, 0); + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/pcieinit_ca9.S b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/pcieinit_ca9.S new file mode 100644 index 00000000000..d465a890354 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/pcieinit_ca9.S @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: pcieinit_ca9.S 654158 2016-08-11 09:30:01Z $ + */ + +#include +#include +#include + +#ifndef __arm__ +#error __arm__ is NOT defined +#endif + +/* Routine begin/end macro */ +#if defined(__thumb__) +#define FUNC(x) THUMBLEAF(x) +#else +#define FUNC(x) LEAF(x) +#endif /* __thumb__ */ + +#ifdef BCMDBG +#define TRACE(x) \ + ldr r9,=(x); \ + ldr r10,=SI_ENUM_BASE_DEFAULT; \ + str r9,[r10,#0x64] + +#define TRACE1(x) \ + mov r9,x; \ + ldr r10,=SI_ENUM_BASE_DEFAULT; \ + str r9,[r10,#0x68] + +#define TRACE2(x) \ + mov r9,x; \ + ldr r10,=SI_ENUM_BASE_DEFAULT; \ + str r9,[r10,#0x64] +#else +#define TRACE(x) +#define TRACE1(x) +#define TRACE2(x) +#endif + + .text + +FUNC(pcie_phy_init) + mov r6,lr + /* + * Sys Init code -- read OTP, program the H/W blocks + * At completion, take a jump to __hw_init_done + */ +__sys_init: + + ldr r0,=SI_ENUM_BASE_DEFAULT /* r0: core regs SI base address */ + ldr r4,[r0,#CC_CAPABILITIES] /* r4: capabitilies */ + and r4,r4,#CC_CAP_OTPSIZE + cmp r4,#0 + beq __hw_init_done + ldr r1,[r0,#CC_CLKDIV] + mov r2,#~CLKD_OTP + and r2,r2,r1 + mov r1,#(0xe << CLKD_OTP_SHIFT) + orr r2,r2,r1 + str r2,[r0,#CC_CLKDIV] /* Update OtpClk in clkdiv with 14 */ + ldr r1,=200 /* Wait for 200 cycles for stable OTP clock */ +spinn: sub r1,r1,#0x1 + cmp r1,#0x0 + bne spinn + lsr r2,r4,#CC_CAP_OTPSIZE_SHIFT /* Get OTP size */ + adrl r1,otp_sizes + lsl r2,r2,#0x2 + ldr r3,[r1,r2] /* Get the OTP size from otp_sizes table (in bytes) */ + + cmp r3,#0x0 /* skip zero size */ + beq __hw_init_done + ldr r1,[r0,#CC_OTPST] + and r1,r1,#OTPS_READY + cmp r1,#0x0 /* 0: OTP is not ready for whatever reason */ + beq __hw_init_done + add r2,r3,r0 /* Seek to the end of OTP region */ + /* Scan entire OTP from END -> BEGIN to find first + * matching hwinit entry */ + sub r2,r2,#2 +1: + add r4,r2,#CC_SROM_OTP + ldrh r1,[r4] + lsl r1,r1,#0x10 + sub r2,r2,#2 + add r4,r2,#CC_SROM_OTP + ldrh r3,[r4] + orr r1,r1,r3 + ldr r4,=0xeaeaeaea /* SID */ + cmp r1,r4 + beq 1f + cmp r0,r2 + blt 1b + /* no hwinit data from OTP */ + b __hw_init_done +1: + add r0,r2,#CC_SROM_OTP + add r0,r0,#4 + mov r1,#0x800 /* for the first delay */ + +__init_next_cmd: + + /* + * delay for N cycles + * read OTP : 32b entry comprise {16b loop count, 8b delay, 8b cmd} + * execute OPT cmd. + * Do_Next if any. + */ + + bl __init_dly /* inter-command delay */ + + ldrh r1,[r0],#2 /* {delay, Cmd} */ + and r2,r1,#0x0f /* extract Cmd */ + cmp r2,#0x1 /* EID (end of init data) */ + beq __hw_init_done /* jump to __hw_init_done on End of Init Data */ + ldrh r3,[r0],#2 /* Loop Count */ + + cmp r2,#0 /* NOP */ + beq __init_next_cmd + + /* load two 32b datum */ + bl __init_load64 + mov r7,r10 /* prepare indirect addr */ + mov r8,r12 /* prepare indirect data */ + + /* + * handle various cases + */ + cmp r2,#4 + beq __init_wr_dir + cmp r2,#5 + beq __init_wr_indir + cmp r2,#6 + beq __init_wr_indir_incaddr + cmp r2,#7 + beq __init_wr_indir_incaddr + cmp r2,#8 + beq __init_wr_dir_incaddr_data + cmp r2,#9 + beq __init_wr_indir_incaddr_data + cmp r2,#10 + beq __init_wr_dir_incaddr_incdata + cmp r2,#11 + beq __init_wr_indir_incaddr_incdata + + /* write direct (cmd=0x02) is a special case of + * write direct multiple (cmd=0x04), under loop count=1 + + * write indirect (cmd=0x03) is a special case of + * write indirect multiple (cmd=0x05), under loop count=1 + */ + + /* write direct multiple (cmd=0x04) */ +__init_wr_dir: + str r12,[r10] /* Mem[addr] = data */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + bl __init_load64 /* load next pair of addr, data */ + bl __init_dly /* inter-op delay */ + b __init_wr_dir + + /* write indirect multiple (cmd=0x05) */ +__init_wr_indir: + bl __init_load64 /* load next pair of addr, data */ + str r10,[r7] /* mem[indirect addr] = addr */ + str r12,[r8] /* mem[indirect data] = data */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + bl __init_dly /* inter-op delay */ + b __init_wr_indir + + /* cmd=0x06 */ + /* write direct, (post) auto-inc address */ +__init_wr_dir_incaddr: + str r12,[r10],#4 /* Mem[addr++] = data, auto-inc addr */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + bl __init_load32 /* load next data */ + bl __init_dly /* inter-op delay */ + b __init_wr_indir_incaddr + + /* cmd=0x07 */ + /* write indirect, (post) auto-inc address */ +__init_wr_indir_incaddr: + bl __init_load64 /* load first addr & data */ +__next_d_0: + str r10,[r7] /* Mem[addr] = addr */ + str r12,[r8] /* Mem[data] = data */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + add r10,r10,#4 /* inc addr by 4 bytes */ + bl __init_load32 /* load next data */ + bl __init_dly /* inter-op delay */ + b __next_d_0 + + /* cmd=0x08 */ + /* write direct multiple, repeatedly the same data to (post) auto-inc address */ +__init_wr_dir_incaddr_data: + str r12,[r10],#4 /* Mem[addr] = data, auto_inc addr */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + bl __init_dly /* inter-op delay */ + b __init_wr_dir_incaddr_data + + /* cmd=0x09 */ + /* write inirect multiple, repeatedly the same data to (post) auto-inc address */ +__init_wr_indir_incaddr_data: + bl __init_load64 /* load first addr & data */ +__next_d_1: + str r10,[r7] /* Mem[addr] = addr */ + str r12,[r8] /* Mem[data] = data */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + add r10,r10,#4 /* inc addr by 4 bytes */ + bl __init_dly /* inter-op delay */ + b __next_d_1 + + /* cmd=0x0a */ + /* write direct multiple, (post) auto-inc addr and data */ +__init_wr_dir_incaddr_incdata: + str r12,[r10],#4 /* Mem[addr] = data, inc addr */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + add r12,r12,#1 /* inc data by 1 */ + bl __init_dly /* inter-op delay */ + b __init_wr_dir_incaddr_incdata + + /* cmd=0x0b */ + /* write indirect multiple, (post) auto-inc addr and data */ +__init_wr_indir_incaddr_incdata: + bl __init_load64 /* load first addr & data */ +__next_d_2: + str r10,[r7] /* Mem[addr] = addr */ + str r12,[r8] /* Mem[data] = data */ + subs r3,r3,#1 /* loop cnt = loop cnt -1 */ + beq __init_next_cmd /* loop cnt = 0 */ + add r10,r10,#4 /* inc addr by 4 bytes */ + add r12,r12,#1 /* inc data by 1 */ + bl __init_dly /* inter-op delay */ + b __next_d_2 + + /* + * Define two Utilities to save the code space. + * + * load one or two 32b datum from current OTP position + * r10 = {r10, r9} + * r12 = {r12, r11} + */ +__init_load64: + ldrh r10,[r0],#2 + ldrh r9,[r0],#2 + orr r10,r9,r10,lsl #16 +__init_load32: + ldrh r12,[r0],#2 + ldrh r11,[r0],#2 + orr r12,r11,r12,lsl #16 + bx lr /* return */ + + /* impose some inter-op and inter-cmd delay + * delay count is passed thru reg. r1 + */ +__init_dly: + asr r9,r1,#11 /* r1/8 cycles, effectively (r1&0x0000ff00) >> 3 */ + cmp r9,#0 + beq __no_dly +__dly_loop: + subs r9,r9,#1 /* loop here */ + bne __dly_loop +__no_dly: + bx lr /* return */ + + /* + * Hardware init. is done + */ + +__hw_init_done: + /* Continuing boot */ + mov lr,r6 + mov pc,lr + +/* OTP sizes in bytes */ +otp_sizes: + .word 0 + .word 256 /* 2048 bits: 32X64 */ + .word 512 /* 4096 bits: 2*32X64 */ + .word 1024 /* 8192 bits: 4*32X64 */ + .word 512 /* 4096 bits: 64X64 */ + .word 768 /* 6144 bits: 5 32X64 */ + .word 0 /* 512 bits: dont care */ + .word 128 /* 1024 bits: 8X64 */ + +END(pcie_phy_init) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/spiflash.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/spiflash.c new file mode 100644 index 00000000000..25a765ee0f0 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/spiflash.c @@ -0,0 +1,1282 @@ +/* + * Broadcom QSPI serial flash interface + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: spiflash.c 596126 2015-10-29 19:53:48Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef FLASH_SPI_MAX_PAGE_SIZE +#define FLASH_SPI_MAX_PAGE_SIZE (256) +#endif + +#ifdef BCMDBG +#define SPIFL_MSG(args) printf args +#else +#define SPIFL_MSG(args) +#endif /* BCMDBG */ + +#define MSPI_CALC_TIMEOUT(bytes, baud) ((((bytes * 9000)/baud) * 110)/100 + 1) + +/* Private global state */ +static hndsflash_t spiflash; + +static int bspi_enabled = 1; +static bool firsttime = TRUE; + +/* Prototype */ +static int spiflash_read(hndsflash_t *spifl, uint offset, uint len, const uchar *buf); +static int spiflash_write(hndsflash_t *spifl, uint offset, uint len, const uchar *buf); +static int spiflash_erase(hndsflash_t *spifl, uint offset); +static int spiflash_poll(hndsflash_t *spifl, uint offset); +static int spiflash_commit(hndsflash_t *spifl, uint offset, uint len, const uchar *buf); +static int spiflash_open(si_t *sih, qspiregs_t *qspi); + +/* Disable Boot SPI */ +static void +mspi_disable_bspi(osl_t *osh, qspiregs_t *qspi) +{ + int i, j; + unsigned int lval; + + if (bspi_enabled == 0) + return; + + lval = R_REG(osh, &qspi->bspi_mast_n_boot_ctrl); + if ((lval & 1) == 1) + return; + + for (i = 0; i < 1000; i++) { + lval = R_REG(osh, &qspi->bspi_busy_status); + if ((lval & 1) == 0) { + W_REG(osh, &qspi->bspi_mast_n_boot_ctrl, 0x1); + bspi_enabled = 0; + for (j = 0; j < 1000; j++); + return; + } + } +} + +/* Enable Boot SPI */ +static void +mspi_enable_bspi(osl_t *osh, qspiregs_t *qspi) +{ + unsigned int lval; + + if (bspi_enabled == 1) + return; + + lval = R_REG(osh, &qspi->bspi_mast_n_boot_ctrl); + if ((lval & 1) == 0) + return; + + W_REG(osh, &qspi->bspi_mast_n_boot_ctrl, 0x0); + + bspi_enabled = 1; + return; +} + +static int +mspi_wait(osl_t *osh, qspiregs_t *qspi, unsigned int timeout_ms) +{ + unsigned int lval; + unsigned int loopCnt = ((timeout_ms * 1000) / 10) + 1; + unsigned int count; + int rc = -1; + + /* We must wait mspi_spcr2 spe bit clear before reading mspi_mspi_status */ + while (1) { + lval = R_REG(osh, &qspi->mspi_spcr2); + if ((lval & MSPI_SPCR2_spe_MASK) == 0) + break; + } + + /* Check status */ + for (count = 0; count < loopCnt; count++) { + lval = R_REG(osh, &qspi->mspi_mspi_status); + if (lval & MSPI_MSPI_STATUS_SPIF_MASK) { + rc = 0; + break; + } + + /* Create some delay 5 times bigger */ + OSL_DELAY(100); + } + + W_REG(osh, &qspi->mspi_mspi_status, 0); + if (rc) { + SPIFL_MSG(("Wait timeout\n")); + } + + return rc; +} + +static int +mspi_writeread(osl_t *osh, qspiregs_t *qspi, unsigned char *w_buf, + unsigned char write_len, unsigned char *r_buf, unsigned char read_len) +{ + unsigned int lval; + unsigned char i, len; + + len = write_len + read_len; + for (i = 0; i < len; i++) { + if (i < write_len) { + /* Transmit Register File MSB */ + W_REG(osh, &qspi->mspi_txram[i * 2], (unsigned int)w_buf[i]); + } + + lval = SPI_CDRAM_CONT | SPI_CDRAM_PCS_DISABLE_ALL | SPI_CDRAM_PCS_DSCK; + lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs2); + /* Command Register File */ + W_REG(osh, &qspi->mspi_cdram[i], lval); + } + + lval = SPI_CDRAM_PCS_DISABLE_ALL | SPI_CDRAM_PCS_DSCK; + lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs2); + /* Command Register File */ + W_REG(osh, &qspi->mspi_cdram[len - 1], lval); + + /* Set queue pointers */ + W_REG(osh, &qspi->mspi_newqp, 0); + W_REG(osh, &qspi->mspi_endqp, len - 1); + + /* Start SPI transfer */ + lval = R_REG(osh, &qspi->mspi_spcr2); + lval |= MSPI_SPCR2_spe_MASK; + W_REG(osh, &qspi->mspi_spcr2, lval); + + /* Wait for SPI to finish */ + if (mspi_wait(osh, qspi, MSPI_CALC_TIMEOUT(len, MAX_SPI_BAUD)) != 0) + return 0; + + W_REG(osh, &qspi->mspi_write_lock, 0); + + for (i = write_len; i < len; ++i) { + /* Data stored in the transmit register file LSB */ + r_buf[i-write_len] = (unsigned char)R_REG(osh, &qspi->mspi_rxram[1 + (i * 2)]); + } + + return 1; +} + +static int +mspi_writeread_continue(osl_t *osh, qspiregs_t *qspi, unsigned char *w_buf, + unsigned char write_len, unsigned char *r_buf, unsigned char read_len) +{ + unsigned int lval; + unsigned char i, len; + + len = write_len + read_len; + for (i = 0; i < len; i++) { + if (i < write_len) + W_REG(osh, &qspi->mspi_txram[i * 2], (unsigned int)w_buf[i]); + + lval = SPI_CDRAM_CONT | SPI_CDRAM_PCS_DISABLE_ALL | SPI_CDRAM_PCS_DSCK; + lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs2); + W_REG(osh, &qspi->mspi_cdram[i], lval); + } + + /* Set queue pointers */ + W_REG(osh, &qspi->mspi_newqp, 0); + W_REG(osh, &qspi->mspi_endqp, len - 1); + + W_REG(osh, &qspi->mspi_write_lock, 1); + + /* Start SPI transfer */ + lval = R_REG(osh, &qspi->mspi_spcr2); + lval |= MSPI_SPCR2_cont_after_cmd_MASK | MSPI_SPCR2_spe_MASK; + W_REG(osh, &qspi->mspi_spcr2, lval); + + /* Wait for SPI to finish */ + if (mspi_wait(osh, qspi, MSPI_CALC_TIMEOUT(len, MAX_SPI_BAUD)) != 0) + return 0; + + for (i = write_len; i < len; ++i) + r_buf[i-write_len] = (unsigned char)R_REG(osh, &qspi->mspi_rxram[1 + (i * 2)]); + + return 1; +} + +/* Command codes for the flash_command routine */ +#define FLASH_READ 0x03 /* read data from memory array */ +#define FLASH_READ_FAST 0x0B /* read data from memory array */ +#define FLASH_PROG 0x02 /* program data into memory array */ +#define FLASH_WREN 0x06 /* set write enable latch */ +#define FLASH_WRDI 0x04 /* reset write enable latch */ +#define FLASH_RDSR 0x05 /* read status register */ +#define FLASH_WRST 0x01 /* write status register */ +#define FLASH_EWSR 0x50 /* enable write status */ +#define FLASH_WORD_AAI 0xAD /* auto address increment word program */ +#define FLASH_AAI 0xAF /* auto address increment program */ + +#define SST_FLASH_CERASE 0x60 /* erase all sectors in memory array */ +#define SST_FLASH_SERASE 0x20 /* erase one sector in memroy array */ +#define SST_FLASH_RDID 0x90 /* read manufacturer and product id */ + +#define ATMEL_FLASH_CERASE 0x62 /* erase all sectors in memory array */ +#define ATMEL_FLASH_SERASE 0x52 /* erase one sector in memroy array */ +#define ATMEL_FLASH_RDID 0x15 /* read manufacturer and product id */ + +#define ATMEL_FLASH_PSEC 0x36 /* protect sector */ +#define ATMEL_FLASH_UNPSEC 0x39 /* unprotect sector */ +#define ATMEL_FLASH_RDPREG 0x3C /* read protect sector registers */ + +#define AMD_FLASH_CERASE 0xC7 /* erase all sectors in memory array */ +#define AMD_FLASH_SERASE 0xD8 /* erase one sector in memroy array */ +#define AMD_FLASH_RDID 0xAB /* read manufacturer and product id */ + +#define SPAN_FLASH_CERASE 0xC7 /* erase all sectors in memory array */ +#define SPAN_FLASH_SERASE 0xD8 /* erase one sector in memory array */ +#define SPAN_FLASH_RDID 0x9F /* read manufacturer and product id */ + +/* Spansion commands for 4-byte addressing */ +#define SPAN_FLASH_BRWR 0x17 /* bank register write */ +#define SPAN_FLASH_4PP 0x12 /* page program with 4-byte address */ +#define SPAN_FLASH_4P4E 0x21 /* parameter 4-kB secotor erase with 4-byte address */ +#define SPAN_FLASH_4SE 0xDC /* sectore erase with 4-byte address */ + +#define ST_FLASH_RDID 0x9F /* read manufacturer and product id */ +#define ST_FLASH_RDFSR 0x70 /* read flag status register */ + +/* ATMEL's manufacturer ID */ +#define ATMELPART 0x1F + +/* A list of ATMEL device ID's - add others as needed */ +#define ID_AT25F512 0x60 +#define ID_AT25F512A 0x65 +#define ID_AT25F2048 0x63 +#define ID_AT26F004 0x04 +#define ID_AT25DF041A 0x44 + +/* AMD's device ID */ +#define AMD_S25FL002D 0x11 + +/* SST's manufacturer ID */ +#define SSTPART 0xBF + +/* A list of SST device ID's - add others as needed */ +#define ID_SST25VF016B 0x41 +#define ID_SST25VF020 0x43 +#define ID_SST25VF040 0x44 +#define ID_SST25VF080 0x80 + +/* Winbond/NexFlash's manufacturer ID */ +#define NXPART 0xEF + +/* A list of NexFlash device ID's - add others as needed */ +#define ID_NX25P20 0x11 +#define ID_NX25P40 0x12 +#define ID_W25X16 0x14 +#define ID_W25X32 0x15 +#define ID_W25X64 0x16 + +/* StFlash's manufacturer ID */ +#define STPART 0x12 + +/* A list of StFlash device ID's - add others as needed */ +#define ID_M25P40 0x12 + +/* SPANSION manufacturer ID */ +#define SPANPART 0x01 + +/* SPANSION device ID's */ +#define ID_SPAN25FL002A 0x11 +#define ID_SPAN25FL004A 0x12 +#define ID_SPAN25FL008A 0x13 +#define ID_SPAN25FL016A 0x14 +#define ID_SPAN25FL032A 0x15 +#define ID_SPAN25FL064A 0x16 +#define ID_SPAN25FL128A 0x17 + +/* EON manufacturer ID */ +#define EONPART 0x1C +/* NUMONYX manufacturer ID */ +#define NUMONYXPART 0x20 +/* Macronix manufacturer ID */ +#define MACRONIXPART 0xC2 + +/* JEDEC device ID */ +#define ID_M25P64 0x17 + +/* Use READ_ID (0x90) command + * Manufacturer Identification - 1 byte + * Device Identification - 2 bytes + * Extended Device Identification - 2 bytes + */ +#define MSPI_IDS_READLEN 5 + +/* Enable/disable BSPI 4-byte mode read */ +static void +spiflash_set_4byte_mode(hndsflash_t *spifl, int enable) +{ + osl_t *osh = si_osh(spifl->sih); + qspiregs_t *qspi = (qspiregs_t *)spifl->core; + unsigned char cmd[1]; + + /* Use MSPI to configure flash for entering/exiting 4-byte mode */ + mspi_disable_bspi(osh, qspi); + cmd[0] = SPI_WREN_CMD; + mspi_writeread(osh, qspi, cmd, 1, NULL, 0); + if (spifl->vendor_id == SPANPART) + cmd[0] = enable? SPAN_FLASH_BRWR : SPI_EX4B_CMD; + else + cmd[0] = enable? SPI_EN4B_CMD : SPI_EX4B_CMD; + mspi_writeread(osh, qspi, cmd, 1, NULL, 0); + cmd[0] = SPI_WRDI_CMD; + mspi_writeread(osh, qspi, cmd, 1, NULL, 0); + + if (enable) { + /* Enable 32-bit address */ + OR_REG(osh, &qspi->bspi_bits_per_phase, BSPI_BITS_PER_PHASE_ADDR_MARK); + } else { + /* Disable 32-bit address */ + AND_REG(osh, &qspi->bspi_bits_per_phase, ~BSPI_BITS_PER_PHASE_ADDR_MARK); + } + + /* BSPI by default */ + mspi_enable_bspi(osh, qspi); +} + +static uint16 +NTOS(unsigned char *a) +{ + uint16 v; + v = (a[0]*256) + a[1]; + return v; +} + +static unsigned short +mspi_read_id(osl_t *osh, qspiregs_t *qspi) +{ + unsigned char cmd[4]; + unsigned char data[5]; + + /* Try SST flashes read product id command */ + cmd[0] = SST_FLASH_RDID; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + if (mspi_writeread(osh, qspi, cmd, 4, data, 2)) { + if (data[0] == SSTPART || data[0] == NXPART) { + return NTOS(data); + } + } + + /* Try ATMEL flashes read product id command */ + cmd[0] = ATMEL_FLASH_RDID; + if (mspi_writeread(osh, qspi, cmd, 1, data, 2)) { + if (data[0] == ATMELPART) { + return NTOS(data); + } + } + + /* Try SPANSION flashes read product id command */ + cmd[0] = SPAN_FLASH_RDID; + if (mspi_writeread(osh, qspi, cmd, 1, data, 3)) { + if (data[0] == ATMELPART) { + return NTOS(data); + } + + if ((data[0] == NUMONYXPART) || (data[0] == SPANPART) || + (data[0] == EONPART) || (data[0] == MACRONIXPART)) { + data[1] = data[2]; + return NTOS(data); + } + } + + /* + * AMD_FLASH_RDID is the same as RES command for SPAN, + * so it has to be the last one. + */ + cmd[0] = AMD_FLASH_RDID; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + if (mspi_writeread(osh, qspi, cmd, 4, data, 2)) { + if (data[0] == AMD_S25FL002D || data[0] == STPART) { + return NTOS(data); + } + } + + return 0; +} + +static int +bspi_sector_erase(hndsflash_t *spifl, qspiregs_t *qspi, unsigned int offset) +{ + si_t *sih = spifl->sih; + osl_t *osh; + int result = 0; + unsigned char cmd[5]; + unsigned char data; + int idx; + + ASSERT(sih); + osh = si_osh(sih); + switch (spifl->type) { + case QSPIFLASH_ST: + cmd[0] = SPI_WREN_CMD; + if ((result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0)) != 1) + break; + + idx = 0; + if (spifl->vendor_id == SPANPART && (spifl->device_id & 0xff) >= 0x19) + cmd[idx++] = (spifl->blocksize < (64 * 1024)) ? + SPAN_FLASH_4P4E : SPAN_FLASH_4SE; + else + cmd[idx++] = (spifl->blocksize < (64 * 1024)) ? SPI_SSE_CMD : SPI_SE_CMD; + if (spifl->size > 0x1000000) { + cmd[idx++] = ((offset & 0xFF000000) >> 24); + } + cmd[idx++] = ((offset & 0x00FF0000) >> 16); + cmd[idx++] = ((offset & 0x0000FF00) >> 8); + cmd[idx++] = (offset & 0x000000FF); + if ((result = mspi_writeread(osh, qspi, cmd, idx, NULL, 0)) != 1) + break; + + /* Check for ST Write In Progress bit */ + do { + cmd[0] = SPI_RDSR_CMD; + if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1) + break; + } while(data & 0x01); /* busy check */ + + if (result != 1) + break; + + /* disable the write */ + cmd[0] = SPI_WRDI_CMD; + result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0); + break; + + case QSPIFLASH_AT: + cmd[0] = SPI_AT_PAGE_ERASE; + offset = offset << 1; + cmd[1] = ((offset & 0x00FF0000) >> 16); + cmd[2] = ((offset & 0x0000FF00) >> 8); + cmd[3] = (offset & 0x000000FF); + if ((result = mspi_writeread(osh, qspi, cmd, 4, NULL, 0)) != 1) + break; + + /* Check for Atmel Ready bit */ + do { + cmd[0] = SPI_AT_STATUS; + if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1) + break; + } while(data & 0x80); /* busy check */ + + if (result != 1) + break; + + /* disable the write */ + cmd[0] = SPI_WRDI_CMD; + result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0); + break; + } + + return result; +} + +static int +bspi2_st_page_program(hndsflash_t *spifl, qspiregs_t *qspi, unsigned int offset, + unsigned char *buf, int len) +{ + si_t *sih = spifl->sih; + osl_t *osh; + int result = 0; + int i, len_total; + static unsigned char cmd[FLASH_SPI_MAX_PAGE_SIZE+5]; + unsigned char data; + int idx; + + ASSERT(sih); + osh = si_osh(sih); + if (len >(FLASH_SPI_MAX_PAGE_SIZE+4)) /* Max bytes per transaction */ + goto done; + + cmd[0] = SPI_WREN_CMD; + if ((result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0)) != 1) + goto done; + + idx = 0; + if (spifl->vendor_id == SPANPART && (spifl->device_id & 0xff) >= 0x19) + cmd[idx++] = SPAN_FLASH_4PP; + else + cmd[idx++] = SPI_PP_CMD; + if (spifl->size > 0x1000000) { + cmd[idx++] = ((offset & 0xFF000000) >> 24); + } + cmd[idx++] = ((offset & 0x00FF0000) >> 16); + cmd[idx++] = ((offset & 0x0000FF00) >> 8); + cmd[idx++] = (offset & 0x000000FF); + + /* + * If new SPI has fix for byte orderig, define FLASH_SPI_BYTE_ORDER_FIX + * to 1 in qspi_core.h + */ +#if defined(IL_BIGENDIAN) && !defined(FLASH_SPI_BYTE_ORDER_FIX) + /* + * mspi does not handle byte ordering for be mode. Handle it here. + * Let's assume len is multiple of 4 + */ + for (i = 0; i < len; i = i+4) { + cmd[i + idx + 0] = buf[i + 3]; + cmd[i + idx + 1] = buf[i + 2]; + cmd[i + idx + 2] = buf[i + 1]; + cmd[i + idx + 3] = buf[i + 0]; + } +#else + for (i = 0; i < len; ++i) + cmd[i + idx] = buf[i]; +#endif + + i = 0; + len_total = len + idx; + + while (len_total > 16) { + if ((result = mspi_writeread_continue(osh, qspi, cmd + i, 16, NULL, 0)) != 1) + goto done; + i += 16; + len_total -= 16; + } + + if (len_total <= 16 && len_total > 0) { + if ((result = mspi_writeread(osh, qspi, cmd+i, len_total, NULL, 0)) != 1) + goto done; + } + + do { + cmd[0] = SPI_RDSR_CMD; + if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1) + goto done; + } while(data & 0x01 /* busy*/); + + /* disable the write */ + cmd[0] = SPI_WRDI_CMD; + if ((result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0)) != 1) + goto done; + +done: + return result; +} + +static int +bspi2_at_page_program(osl_t *osh, qspiregs_t *qspi, hndsflash_t *spifl, unsigned int offset, + unsigned char *buf, int len) +{ + int result = 0; + int i, len_total; + static unsigned char cmd[FLASH_SPI_MAX_PAGE_SIZE+4]; + unsigned char data; + uint32 page, byte, mask; + + mask = spifl->blocksize - 1; + page = (offset & ~mask) << 1; + byte = offset & mask; + + /* Read main memory page into buffer 1 */ + if (byte || (len < spifl->blocksize)) { + cmd[0] = SPI_AT_BUF1_LOAD; + cmd[1] = ((page & 0x00FF0000) >> 16); + cmd[2] = ((page & 0x0000FF00) >> 8); + cmd[3] = (page & 0x000000FF); + + if ((result = mspi_writeread(osh, qspi, cmd, 4, NULL, 0)) != 1) + goto done; + + do { + cmd[0] = SPI_AT_STATUS; + if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1) + goto done; + } while(!(data & SPI_AT_READY) /* not ready */); + } + + /* Write into buffer 1 */ + cmd[0] = SPI_AT_BUF1_WRITE; + cmd[1] = ((byte & 0x00FF0000) >> 16); + cmd[2] = ((byte & 0x0000FF00) >> 8); + cmd[3] = (byte & 0x000000FF); + /* + * If new SPI has fix for byte orderig, define FLASH_SPI_BYTE_ORDER_FIX + * to 1 in qspi_core.h + */ +#if defined(IL_BIGENDIAN) && !defined(FLASH_SPI_BYTE_ORDER_FIX) + /* + * mspi does not handle byte ordering for be mode. Handle it here. + * Let's assume len is multiple of 4 + */ + for (i = 0; i < len; i = i+4) { + cmd[i+4] = buf[i+3]; + cmd[i+5] = buf[i+2]; + cmd[i+6] = buf[i+1]; + cmd[i+7] = buf[i]; + } +#else + for (i = 0; i < len; ++i) + cmd[i+4] = buf[i]; +#endif + + i = 0; + len_total = len + 4; + + while (len_total > 16) { + if ((result = mspi_writeread_continue(osh, qspi, cmd + i, 16, NULL, 0)) != 1) + goto done; + i += 16; + len_total -= 16; + } + + if (len_total <= 16 && len_total > 0) { + if ((result = mspi_writeread(osh, qspi, cmd+i, len_total, NULL, 0)) != 1) + goto done; + } + + /* Write buffer 1 into main memory page */ + cmd[0] = SPI_AT_BUF1_PROGRAM; + cmd[1] = ((page & 0x00FF0000) >> 16); + cmd[2] = ((page & 0x0000FF00) >> 8); + cmd[3] = (page & 0x000000FF); + result = mspi_writeread(osh, qspi, cmd, 4, NULL, 0); + +done: + return result; +} + +static int bspi_poll(hndsflash_t *spifl, qspiregs_t *qspi, unsigned int offset) +{ + si_t *sih = spifl->sih; + osl_t *osh; + int result = 1; + unsigned char cmd[4]; + unsigned char data; + + ASSERT(sih); + + osh = si_osh(sih); + + switch (spifl->device_id & 0x00ff) + { + case 0x20: + do { + cmd[0] = ST_FLASH_RDFSR; + if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1) { + result = 0; + break; + } + } while ((data & 0x80) == 0); + break; + default: + break; + } + + return result; +} + +/* Initialize serial flash access */ +hndsflash_t * +spiflash_init(si_t *sih) +{ + qspiregs_t *qspi; + uint16 device_id; + const char *name = ""; + osl_t *osh; + uint8 vendor_id; + int force_3byte_mode = 0; + + ASSERT(sih); + + /* Only support chipcommon revision == 42 for now */ + if (sih->ccrev != 42) + return NULL; + + if ((qspi = (qspiregs_t *)si_setcore(sih, NS_QSPI_CORE_ID, 0)) == NULL) + return NULL; + + if (!firsttime && spiflash.size != 0) + return &spiflash; + + osh = si_osh(sih); + + bzero(&spiflash, sizeof(spiflash)); + spiflash.sih = sih; + spiflash.core = (void *)qspi; + spiflash.read = spiflash_read; + spiflash.write = spiflash_write; + spiflash.erase = spiflash_erase; + spiflash.commit = spiflash_commit; + + spiflash.device_id = device_id = mspi_read_id(osh, qspi); + spiflash.vendor_id = vendor_id = (device_id >> 8); + switch (vendor_id) { + case SPANPART: + case MACRONIXPART: + case NUMONYXPART: + case NXPART: + /* ST compatible */ + if (vendor_id == SPANPART) + name = "ST compatible"; + else if (vendor_id == MACRONIXPART) + name = "ST compatible (Marconix)"; + else if (vendor_id == NXPART) + name = "ST compatible (Winbond/NexFlash)"; + else + name = "ST compatible (Micron)"; + + spiflash.type = QSPIFLASH_ST; + spiflash.blocksize = 64 * 1024; + + switch ((unsigned short)(device_id & 0x00ff)) { + case 0x11: + /* ST M25P20 2 Mbit Serial Flash */ + spiflash.numblocks = 4; + break; + case 0x12: + /* ST M25P40 4 Mbit Serial Flash */ + spiflash.numblocks = 8; + break; + case 0x13: + spiflash.numblocks = 16; + break; + case 0x14: + /* ST M25P16 16 Mbit Serial Flash */ + spiflash.numblocks = 32; + break; + case 0x15: + /* ST M25P32 32 Mbit Serial Flash */ + spiflash.numblocks = 64; + break; + case 0x16: + /* ST M25P64 64 Mbit Serial Flash */ + spiflash.numblocks = 128; + break; + case 0x17: + case 0x18: + /* ST M25FL128 128 Mbit Serial Flash */ + spiflash.numblocks = 256; + break; + case 0x19: + spiflash.numblocks = 512; + break; + case 0x20: + spiflash.numblocks = 1024; + /* Special poll requirement for Micron N25Q512 */ + spiflash.poll = spiflash_poll; + break; + } + break; + + case SSTPART: + name = "SST"; + spiflash.type = QSPIFLASH_ST; + spiflash.blocksize = 4 * 1024; + switch ((unsigned char)(device_id & 0x00ff)) { + case 1: + /* SST25WF512 512 Kbit Serial Flash */ + spiflash.numblocks = 16; + break; + case 0x48: + /* SST25VF512 512 Kbit Serial Flash */ + spiflash.numblocks = 16; + break; + case 2: + /* SST25WF010 1 Mbit Serial Flash */ + spiflash.numblocks = 32; + break; + case 0x49: + /* SST25VF010 1 Mbit Serial Flash */ + spiflash.numblocks = 32; + break; + case 3: + /* SST25WF020 2 Mbit Serial Flash */ + spiflash.numblocks = 64; + break; + case 0x43: + /* SST25VF020 2 Mbit Serial Flash */ + spiflash.numblocks = 64; + break; + case 4: + /* SST25WF040 4 Mbit Serial Flash */ + spiflash.numblocks = 128; + break; + case 0x44: + /* SST25VF040 4 Mbit Serial Flash */ + spiflash.numblocks = 128; + break; + case 0x8d: + /* SST25VF040B 4 Mbit Serial Flash */ + spiflash.numblocks = 128; + break; + case 5: + /* SST25WF080 8 Mbit Serial Flash */ + spiflash.numblocks = 256; + break; + case 0x8e: + /* SST25VF080B 8 Mbit Serial Flash */ + spiflash.numblocks = 256; + break; + case 0x41: + /* SST25VF016 16 Mbit Serial Flash */ + spiflash.numblocks = 512; + break; + case 0x4a: + /* SST25VF032 32 Mbit Serial Flash */ + spiflash.numblocks = 1024; + break; + case 0x4b: + /* SST25VF064 64 Mbit Serial Flash */ + spiflash.numblocks = 2048; + break; + } + break; + + case ATMELPART: + /* SFLASH_AT_STATUS not implement */ + name = "Atmel"; + spiflash.type = QSPIFLASH_AT; + switch ((char)(device_id & 0x00ff)) { + case ID_AT25F512: + spiflash.numblocks = 2; + spiflash.blocksize = 32 * 1024; + break; + + case ID_AT25F2048: + spiflash.numblocks = 4; + spiflash.blocksize = 64 * 1024; + break; + default: + break; + } + break; + + default: + spiflash.numblocks = 0; + SPIFL_MSG(("Unknown flash, device_id:0x%02X\n", device_id)); + return NULL; + } + + /* Open device here */ + spiflash_open(sih, qspi); + + spiflash.size = spiflash.blocksize * spiflash.numblocks; + + if (BCM4707_CHIP(CHIPID(sih->chip))) { + uint32 chip_rev, straps_ctrl; + uint32 *srab_base, *dmu_base; + /* Get chip revision */ + srab_base = (uint32 *)REG_MAP(CHIPCB_SRAB_BASE, SI_CORE_SIZE); + W_REG(osh, (uint32 *)((uint32)srab_base + CHIPCB_SRAB_CMDSTAT_OFFSET), 0x02400001); + chip_rev = R_REG(osh, + (uint32 *)((uint32)srab_base + CHIPCB_SRAB_RDL_OFFSET)) & 0xff; + REG_UNMAP(srab_base); + if (CHIPID(sih->chip) == BCM4707_CHIP_ID && chip_rev < 2) { + force_3byte_mode = 1; + } + /* Check 4BYTE_MODE strap */ + dmu_base = (uint32 *)REG_MAP(CHIPCB_DMU_BASE, SI_CORE_SIZE); + straps_ctrl = R_REG(osh, + (uint32 *)((uint32)dmu_base + CHIPCB_CRU_STRAPS_CTRL_OFFSET)); + REG_UNMAP(dmu_base); + if (!(straps_ctrl & CHIPCB_CRU_STRAPS_4BYTE)) + force_3byte_mode = 1; + } + /* NOR flash size check. */ + if (force_3byte_mode && (spiflash.size > SI_FLASH_WINDOW)) { + SPIFL_MSG(("NOR flash size %dMB is bigger than %dMB, limit it to %dMB\n", + (spiflash.size >> 20), (SI_FLASH_WINDOW >> 20), + (SI_FLASH_WINDOW >> 20))); + spiflash.size = SI_FLASH_WINDOW; + } else if (spiflash.size > SI_NS_FLASH_WINDOW) { + SPIFL_MSG(("NOR flash size %dMB is bigger than %dMB, limit it to %dMB\n", + (spiflash.size >> 20), (SI_NS_FLASH_WINDOW >> 20), + (SI_NS_FLASH_WINDOW >> 20))); + spiflash.size = SI_NS_FLASH_WINDOW; + } + + spiflash.phybase = SI_NS_NORFLASH; + if (spiflash.size) + spiflash.base = (uint32)REG_MAP(SI_NS_NORFLASH, spiflash.size); + + if (firsttime) { + if (spiflash.size == 0) + printf("ERROR: Unknown flash, device_id:0x%02X\n", device_id); + else { + /* Enter 4-byte mode if size > 16MB */ + if (spiflash.size > 0x1000000) { + spiflash_set_4byte_mode(&spiflash, 1); + } else { + spiflash_set_4byte_mode(&spiflash, 0); + } + printf("Found a %s serial flash with %d %dKB blocks; total size %dMB\n", + name, spiflash.numblocks, spiflash.blocksize / 1024, + spiflash.size / (1024 * 1024)); + } + } + + firsttime = FALSE; + return spiflash.size ? &spiflash : NULL; +} + +static int +spiflash_open(si_t *sih, qspiregs_t *qspi) +{ + osl_t *osh = NULL; + unsigned int lval; + + ASSERT(sih); + + osh = si_osh(sih); + + lval = SPI_SYSTEM_CLK / (2 * MAX_SPI_BAUD); + W_REG(osh, &qspi->mspi_spcr0_lsb, lval); + lval = R_REG(osh, &qspi->mspi_spcr0_msb); + lval &= ~(MSPI_SPCR0_MSB_CPOL_MASK | MSPI_SPCR0_MSB_CPHA_MASK | MSPI_SPCR0_MSB_BitS_MASK); + lval |= (MSPI_SPCR0_MSB_MSTR_MASK | (MSPI_SPCR0_MSB_CPOL_MASK | MSPI_SPCR0_MSB_CPHA_MASK | + (0x8 << MSPI_SPCR0_MSB_BitS_SHIFT))); + W_REG(osh, &qspi->mspi_spcr0_msb, lval); + + /* add delay if it is 7422A0 */ + W_REG(osh, &qspi->mspi_spcr1_msb, 128); + + return 0; +} + +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ +static int +spiflash_read(hndsflash_t *spifl, uint offset, uint len, const uchar *buf) +{ + si_t *sih = spifl->sih; + qspiregs_t *qspi = (qspiregs_t *)spifl->core; + osl_t *osh; + uint8 *from, *to; + int cnt, i; + + ASSERT(sih); + + osh = si_osh(sih); + + if (!len) + return 0; + + if ((offset + len) > spifl->size) + return -22; + + if ((len >= 4) && (offset & 3)) + cnt = 4 - (offset & 3); + else if ((len >= 4) && ((uintptr)buf & 3)) + cnt = 4 - ((uintptr)buf & 3); + else + cnt = len; + + from = (uint8 *)((void *)spifl->base + offset); + to = (uint8 *)buf; + + mspi_enable_bspi(osh, qspi); + if (cnt < 4) { + for (i = 0; i < cnt; i ++) { + /* Cannot use R_REG because in bigendian that will + * xor the address and we don't want that here. + */ + *to = *from; + from ++; + to ++; + } + return cnt; + } + + while (cnt >= 4) { + *(uint32 *)to = *(uint32 *)from; + from += 4; + to += 4; + cnt -= 4; + } + + return (len - cnt); +} + +/* Write len bytes starting at offset into buf. Returns number of bytes + * written + */ +static int +spiflash_write(hndsflash_t *spifl, uint offset, uint length, const uchar *buffer) +{ + si_t *sih = spifl->sih; + qspiregs_t *qspi = (qspiregs_t *)spifl->core; + const uint8 *buf = buffer; + int ret = 0; + osl_t *osh; + unsigned i, j, number_byte_to_write; + uchar temp[FLASH_SPI_MAX_PAGE_SIZE+28]; + + ASSERT(sih); + + osh = si_osh(sih); + + if (!length) + return 0; + + if ((offset + length) > spifl->size) + return -22; + + mspi_disable_bspi(osh, qspi); + + switch (spifl->type) { + case QSPIFLASH_ST: + for (i = 0; i < length; i += number_byte_to_write) { + if (i + FLASH_SPI_MAX_PAGE_SIZE >= length) + number_byte_to_write = length - i; + else + number_byte_to_write = FLASH_SPI_MAX_PAGE_SIZE; + + /* to prevent address cross the page boundary of 256 bytes. */ + if (number_byte_to_write > (256 - (i&0xFF))) + number_byte_to_write = 256 - (i&0xFF); + + for (j = 0; j < number_byte_to_write; j++) { + temp[j] = *buf; + buf += 1; + } + if (!bspi2_st_page_program(spifl, qspi, offset + i, &temp[0], + number_byte_to_write)) { + SPIFL_MSG(("Program fail\n")); + ret = -11; + break; + } + + if (spifl->poll && !bspi_poll(spifl, qspi, offset + i)) { + SPIFL_MSG(("Poll fail\n")); + ret = -33; + break; + } + + ret += number_byte_to_write; + } + break; + + case QSPIFLASH_AT: + for (i = 0; i < length; i += number_byte_to_write) { + if (i + FLASH_SPI_MAX_PAGE_SIZE >= length) + number_byte_to_write = length - i; + else + number_byte_to_write = FLASH_SPI_MAX_PAGE_SIZE; + + /* to prevent address cross the page boundary of 256 bytes. */ + if (number_byte_to_write > (256 - (i&0xFF))) + number_byte_to_write = 256 - (i&0xFF); + + for (j = 0; j < number_byte_to_write; j++) { + temp[j] = *buf; + buf += 1; + } + if (!bspi2_at_page_program(osh, qspi, spifl, offset + i, &temp[0], + number_byte_to_write)) { + SPIFL_MSG(("Program fail\n")); + ret = -11; + break; + } + ret += number_byte_to_write; + } + break; + } + + mspi_enable_bspi(osh, qspi); + return ret; +} + +/* Erase a region. Returns number of bytes scheduled for erasure. + * Caller should poll for completion. + */ +static int +spiflash_erase(hndsflash_t *spifl, uint offset) +{ + si_t *sih = spifl->sih; + qspiregs_t *qspi = (qspiregs_t *)spifl->core; + int erase_size = 0; + osl_t *osh = NULL; + + ASSERT(sih); + + osh = si_osh(sih); + + if (offset >= spifl->size) + return -22; + + mspi_disable_bspi(osh, qspi); + + if (bspi_sector_erase(spifl, qspi, offset)) + erase_size = spifl->blocksize; + + mspi_enable_bspi(osh, qspi); + + return erase_size; +} + +/* + * Poll function called after write/erase operations. Returns 0 when poll + * completes. + */ +static int +spiflash_poll(hndsflash_t *spifl, uint offset) +{ + int result = 0; + si_t *sih = spifl->sih; + qspiregs_t *qspi = (qspiregs_t *)spifl->core; + osl_t *osh = NULL; + + ASSERT(sih); + + osh = si_osh(sih); + + if (offset >= spifl->size) + return -22; + + mspi_disable_bspi(osh, qspi); + + switch (spifl->type) { + case QSPIFLASH_ST: + /* Larger part such as the Micron 25Q512A (64MB) requires the flash status register + * (FSR) polled after write/erase. + */ + if (!bspi_poll(spifl, qspi, offset)) { + result = 1; /* Poll failed */ + } + break; + + default: + /* Nothing to do */ + break; + } + + mspi_enable_bspi(osh, qspi); + + return result; +} + +/* + * writes the appropriate range of flash, a NULL buf simply erases + * the region of flash + */ +static int +spiflash_commit(hndsflash_t *spifl, uint offset, uint len, const uchar *buf) +{ + si_t *sih = spifl->sih; + uchar *block = NULL, *cur_ptr, *blk_ptr; + uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; + uint blk_offset, blk_len, copied; + int bytes, ret = 0; + osl_t *osh; + + ASSERT(sih); + + osh = si_osh(sih); + + /* Check address range */ + if (len <= 0) + return 0; + + if ((offset + len) > spifl->size) + return -1; + + blocksize = spifl->blocksize; + mask = blocksize - 1; + + /* Allocate a block of mem */ + if (!(block = MALLOC(osh, blocksize))) + return -1; + + while (len) { + /* Align offset */ + cur_offset = offset & ~mask; + cur_length = blocksize; + cur_ptr = block; + + remainder = blocksize - (offset & mask); + if (len < remainder) + cur_retlen = len; + else + cur_retlen = remainder; + + /* buf == NULL means erase only */ + if (buf) { + /* Copy existing data into holding block if necessary */ + if ((offset & mask) || (len < blocksize)) { + blk_offset = cur_offset; + blk_len = cur_length; + blk_ptr = cur_ptr; + + /* Copy entire block */ + while (blk_len) { + copied = spiflash_read(spifl, blk_offset, blk_len, + blk_ptr); + blk_offset += copied; + blk_len -= copied; + blk_ptr += copied; + } + } + + /* Copy input data into holding block */ + memcpy(cur_ptr + (offset & mask), buf, cur_retlen); + } + + /* Erase block */ + if ((ret = spiflash_erase(spifl, (uint)cur_offset)) < 0) + goto done; + + /* buf == NULL means erase only */ + if (!buf) { + offset += cur_retlen; + len -= cur_retlen; + continue; + } + + /* Write holding block */ + while (cur_length > 0) { + if ((bytes = spiflash_write(spifl, + (uint)cur_offset, + (uint)cur_length, + (uchar *)cur_ptr)) < 0) { + ret = bytes; + goto done; + } + cur_offset += bytes; + cur_length -= bytes; + cur_ptr += bytes; + } + + offset += cur_retlen; + len -= cur_retlen; + buf += cur_retlen; + } + + ret = len; +done: + if (block) + MFREE(osh, block, blocksize); + return ret; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/startarm-ca9.S b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/startarm-ca9.S new file mode 100644 index 00000000000..f4be8231670 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmdrv/shared/startarm-ca9.S @@ -0,0 +1,6010 @@ +/* + * BCM53XXX ARM/Cortext A9 boot code for standalone apps. + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: startarm-ca9.S 654158 2016-08-11 09:30:01Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _CFE_ + +#include +#include "initdata.h" +#include "bsp_config.h" +#include "cfe_devfuncs.h" + +#define c_main cfe_main + +/* + * This is the size of the stack, rounded to KByte boundaries. + */ + +#ifndef CFG_STACK_SIZE +#error "CFG_STACK_SIZE not defined" +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +#define envram_ofs 0x1000 + +#else /* !_CFE_ */ + +#if defined(__thumb__) +#define FUNC(x) THUMBLEAF(x) +#else +#define FUNC(x) LEAF(x) +#endif + +/* Debug macro */ +#ifdef TRACE +#undef TRACE +#endif +#ifdef BCMDBG +#define TRACE(x) \ + ldr r9,=(x); \ + ldr r10,=SI_ENUM_BASE_DEFAULT; \ + str r9,[r10,#0x64] +#else +#define TRACE(x) +#endif + +#define envram_ofs 0x400 + +#if CFG_BIENDIAN +#define CFE_EPTSEAL_REV 0x31454643 +#endif +#define CFE_EPTSEAL 0x43464531 +#define cfe_command_restart 0 + +#endif /* _CFE_ */ + +#ifdef CFG_SHMOO +/* MMU table */ + .section section_mmu_table +page_table: + .word 0x00004c06 + .word 0x00104c06 + .word 0x00204c06 + .word 0x00304c06 + .word 0x00404c06 + .word 0x00504c06 + .word 0x00604c06 + .word 0x00704c06 + .word 0x00804c06 + .word 0x00904c06 + .word 0x00a04c06 + .word 0x00b04c06 + .word 0x00c04c06 + .word 0x00d04c06 + .word 0x00e04c06 + .word 0x00f04c06 + .word 0x01004c06 @DDR_SHMOO_RELATED_CHANGE: make 16MB-32MB area as L1 cacheable write-back mode requested by shmoo memory test + .word 0x01104c06 + .word 0x01204c06 + .word 0x01304c06 + .word 0x01404c06 + .word 0x01504c06 + .word 0x01604c06 + .word 0x01704c06 + .word 0x01804c06 + .word 0x01904c06 + .word 0x01a04c06 + .word 0x01b04c06 + .word 0x01c04c06 + .word 0x01d04c06 + .word 0x01e04c06 + .word 0x01f04c06 + .word 0x02004c06 @DDR_SHMOO_RELATED_CHANGE: make 32MB-128MB area as L1&L2 cacheable write-back mode requested by stress memory test + .word 0x02104c06 + .word 0x02204c06 + .word 0x02304c06 + .word 0x02404c06 + .word 0x02504c06 + .word 0x02604c06 + .word 0x02704c06 + .word 0x02804c06 + .word 0x02904c06 + .word 0x02a04c06 + .word 0x02b04c06 + .word 0x02c04c06 + .word 0x02d04c06 + .word 0x02e04c06 + .word 0x02f04c06 + .word 0x03004c06 + .word 0x03104c06 + .word 0x03204c06 + .word 0x03304c06 + .word 0x03404c06 + .word 0x03504c06 + .word 0x03604c06 + .word 0x03704c06 + .word 0x03804c06 + .word 0x03904c06 + .word 0x03a04c06 + .word 0x03b04c06 + .word 0x03c04c06 + .word 0x03d04c06 + .word 0x03e04c06 + .word 0x03f04c06 + .word 0x04004c06 + .word 0x04104c06 + .word 0x04204c06 + .word 0x04304c06 + .word 0x04404c06 + .word 0x04504c06 + .word 0x04604c06 + .word 0x04704c06 + .word 0x04804c06 + .word 0x04904c06 + .word 0x04a04c06 + .word 0x04b04c06 + .word 0x04c04c06 + .word 0x04d04c06 + .word 0x04e04c06 + .word 0x04f04c06 + .word 0x05004c06 + .word 0x05104c06 + .word 0x05204c06 + .word 0x05304c06 + .word 0x05404c06 + .word 0x05504c06 + .word 0x05604c06 + .word 0x05704c06 + .word 0x05804c06 + .word 0x05904c06 + .word 0x05a04c06 + .word 0x05b04c06 + .word 0x05c04c06 + .word 0x05d04c06 + .word 0x05e04c06 + .word 0x05f04c06 + .word 0x06004c06 + .word 0x06104c06 + .word 0x06204c06 + .word 0x06304c06 + .word 0x06404c06 + .word 0x06504c06 + .word 0x06604c06 + .word 0x06704c06 + .word 0x06804c06 + .word 0x06904c06 + .word 0x06a04c06 + .word 0x06b04c06 + .word 0x06c04c06 + .word 0x06d04c06 + .word 0x06e04c06 + .word 0x06f04c06 + .word 0x07004c06 + .word 0x07104c06 + .word 0x07204c06 + .word 0x07304c06 + .word 0x07404c06 + .word 0x07504c06 + .word 0x07604c06 + .word 0x07704c06 + .word 0x07804c06 + .word 0x07904c06 + .word 0x07a04c06 + .word 0x07b04c06 + .word 0x07c04c06 + .word 0x07d04c06 + .word 0x07e04c06 + .word 0x07f04c06 @ DDR_SHMOO_RELATED_CHANGE: end of L1&L2 cacheable write-back mode + .word 0x08002c02 + .word 0x08102c02 + .word 0x08202c02 + .word 0x08302c02 + .word 0x08402c02 + .word 0x08502c02 + .word 0x08602c02 + .word 0x08702c02 + .word 0x08802c02 + .word 0x08902c02 + .word 0x08a02c02 + .word 0x08b02c02 + .word 0x08c02c02 + .word 0x08d02c02 + .word 0x08e02c02 + .word 0x08f02c02 + .word 0x09002c02 + .word 0x09102c02 + .word 0x09202c02 + .word 0x09302c02 + .word 0x09402c02 + .word 0x09502c02 + .word 0x09602c02 + .word 0x09702c02 + .word 0x09802c02 + .word 0x09902c02 + .word 0x09a02c02 + .word 0x09b02c02 + .word 0x09c02c02 + .word 0x09d02c02 + .word 0x09e02c02 + .word 0x09f02c02 + .word 0x0a002c02 + .word 0x0a102c02 + .word 0x0a202c02 + .word 0x0a302c02 + .word 0x0a402c02 + .word 0x0a502c02 + .word 0x0a602c02 + .word 0x0a702c02 + .word 0x0a802c02 + .word 0x0a902c02 + .word 0x0aa02c02 + .word 0x0ab02c02 + .word 0x0ac02c02 + .word 0x0ad02c02 + .word 0x0ae02c02 + .word 0x0af02c02 + .word 0x0b002c02 + .word 0x0b102c02 + .word 0x0b202c02 + .word 0x0b302c02 + .word 0x0b402c02 + .word 0x0b502c02 + .word 0x0b602c02 + .word 0x0b702c02 + .word 0x0b802c02 + .word 0x0b902c02 + .word 0x0ba02c02 + .word 0x0bb02c02 + .word 0x0bc02c02 + .word 0x0bd02c02 + .word 0x0be02c02 + .word 0x0bf02c02 + .word 0x0c002c02 + .word 0x0c102c02 + .word 0x0c202c02 + .word 0x0c302c02 + .word 0x0c402c02 + .word 0x0c502c02 + .word 0x0c602c02 + .word 0x0c702c02 + .word 0x0c802c02 + .word 0x0c902c02 + .word 0x0ca02c02 + .word 0x0cb02c02 + .word 0x0cc02c02 + .word 0x0cd02c02 + .word 0x0ce02c02 + .word 0x0cf02c02 + .word 0x0d002c02 + .word 0x0d102c02 + .word 0x0d202c02 + .word 0x0d302c02 + .word 0x0d402c02 + .word 0x0d502c02 + .word 0x0d602c02 + .word 0x0d702c02 + .word 0x0d802c02 + .word 0x0d902c02 + .word 0x0da02c02 + .word 0x0db02c02 + .word 0x0dc02c02 + .word 0x0dd02c02 + .word 0x0de02c02 + .word 0x0df02c02 + .word 0x0e002c02 + .word 0x0e102c02 + .word 0x0e202c02 + .word 0x0e302c02 + .word 0x0e402c02 + .word 0x0e502c02 + .word 0x0e602c02 + .word 0x0e702c02 + .word 0x0e802c02 + .word 0x0e902c02 + .word 0x0ea02c02 + .word 0x0eb02c02 + .word 0x0ec02c02 + .word 0x0ed02c02 + .word 0x0ee02c02 + .word 0x0ef02c02 + .word 0x0f002c02 + .word 0x0f102c02 + .word 0x0f202c02 + .word 0x0f302c02 + .word 0x0f402c02 + .word 0x0f502c02 + .word 0x0f602c02 + .word 0x0f702c02 + .word 0x0f802c02 + .word 0x0f902c02 + .word 0x0fa02c02 + .word 0x0fb02c02 + .word 0x0fc02c02 + .word 0x0fd02c02 + .word 0x0fe02c02 + .word 0x0ff02c02 + .word 0x10002c02 + .word 0x10102c02 + .word 0x10202c02 + .word 0x10302c02 + .word 0x10402c02 + .word 0x10502c02 + .word 0x10602c02 + .word 0x10702c02 + .word 0x10802c02 + .word 0x10902c02 + .word 0x10a02c02 + .word 0x10b02c02 + .word 0x10c02c02 + .word 0x10d02c02 + .word 0x10e02c02 + .word 0x10f02c02 + .word 0x11002c02 + .word 0x11102c02 + .word 0x11202c02 + .word 0x11302c02 + .word 0x11402c02 + .word 0x11502c02 + .word 0x11602c02 + .word 0x11702c02 + .word 0x11802c02 + .word 0x11902c02 + .word 0x11a02c02 + .word 0x11b02c02 + .word 0x11c02c02 + .word 0x11d02c02 + .word 0x11e02c02 + .word 0x11f02c02 + .word 0x12002c02 + .word 0x12102c02 + .word 0x12202c02 + .word 0x12302c02 + .word 0x12402c02 + .word 0x12502c02 + .word 0x12602c02 + .word 0x12702c02 + .word 0x12802c02 + .word 0x12902c02 + .word 0x12a02c02 + .word 0x12b02c02 + .word 0x12c02c02 + .word 0x12d02c02 + .word 0x12e02c02 + .word 0x12f02c02 + .word 0x13002c02 + .word 0x13102c02 + .word 0x13202c02 + .word 0x13302c02 + .word 0x13402c02 + .word 0x13502c02 + .word 0x13602c02 + .word 0x13702c02 + .word 0x13802c02 + .word 0x13902c02 + .word 0x13a02c02 + .word 0x13b02c02 + .word 0x13c02c02 + .word 0x13d02c02 + .word 0x13e02c02 + .word 0x13f02c02 + .word 0x14002c02 + .word 0x14102c02 + .word 0x14202c02 + .word 0x14302c02 + .word 0x14402c02 + .word 0x14502c02 + .word 0x14602c02 + .word 0x14702c02 + .word 0x14802c02 + .word 0x14902c02 + .word 0x14a02c02 + .word 0x14b02c02 + .word 0x14c02c02 + .word 0x14d02c02 + .word 0x14e02c02 + .word 0x14f02c02 + .word 0x15002c02 + .word 0x15102c02 + .word 0x15202c02 + .word 0x15302c02 + .word 0x15402c02 + .word 0x15502c02 + .word 0x15602c02 + .word 0x15702c02 + .word 0x15802c02 + .word 0x15902c02 + .word 0x15a02c02 + .word 0x15b02c02 + .word 0x15c02c02 + .word 0x15d02c02 + .word 0x15e02c02 + .word 0x15f02c02 + .word 0x16002c02 + .word 0x16102c02 + .word 0x16202c02 + .word 0x16302c02 + .word 0x16402c02 + .word 0x16502c02 + .word 0x16602c02 + .word 0x16702c02 + .word 0x16802c02 + .word 0x16902c02 + .word 0x16a02c02 + .word 0x16b02c02 + .word 0x16c02c02 + .word 0x16d02c02 + .word 0x16e02c02 + .word 0x16f02c02 + .word 0x17002c02 + .word 0x17102c02 + .word 0x17202c02 + .word 0x17302c02 + .word 0x17402c02 + .word 0x17502c02 + .word 0x17602c02 + .word 0x17702c02 + .word 0x17802c02 + .word 0x17902c02 + .word 0x17a02c02 + .word 0x17b02c02 + .word 0x17c02c02 + .word 0x17d02c02 + .word 0x17e02c02 + .word 0x17f02c02 + .word 0x18002c02 + .word 0x18102c02 + .word 0x18202c02 + .word 0x18302c02 + .word 0x18402c02 + .word 0x18502c02 + .word 0x18602c02 + .word 0x18702c02 + .word 0x18802c02 + .word 0x18902c02 + .word 0x18a02c02 + .word 0x18b02c02 + .word 0x18c02c02 + .word 0x18d02c02 + .word 0x18e02c02 + .word 0x18f02c02 + .word 0x19002c02 + .word 0x19102c02 + .word 0x19202c02 + .word 0x19302c02 + .word 0x19402c02 + .word 0x19502c02 + .word 0x19602c02 + .word 0x19702c02 + .word 0x19802c02 + .word 0x19902c02 + .word 0x19a02c02 + .word 0x19b02c02 + .word 0x19c02c02 + .word 0x19d02c02 + .word 0x19e02c02 + .word 0x19f02c02 + .word 0x1a002c02 + .word 0x1a102c02 + .word 0x1a202c02 + .word 0x1a302c02 + .word 0x1a402c02 + .word 0x1a502c02 + .word 0x1a602c02 + .word 0x1a702c02 + .word 0x1a802c02 + .word 0x1a902c02 + .word 0x1aa02c02 + .word 0x1ab02c02 + .word 0x1ac02c02 + .word 0x1ad02c02 + .word 0x1ae02c02 + .word 0x1af02c02 + .word 0x1b002c02 + .word 0x1b102c02 + .word 0x1b202c02 + .word 0x1b302c02 + .word 0x1b402c02 + .word 0x1b502c02 + .word 0x1b602c02 + .word 0x1b702c02 + .word 0x1b802c02 + .word 0x1b902c02 + .word 0x1ba02c02 + .word 0x1bb02c02 + .word 0x1bc02c02 + .word 0x1bd02c02 + .word 0x1be02c02 + .word 0x1bf02c02 + .word 0x1c002c02 @ bcm95301x_svk_iproc_nand_config: make NAND flash code L1&L2 cachable + .word 0x1c102c02 + .word 0x1c202c02 + .word 0x1c302c02 + .word 0x1c402c02 + .word 0x1c502c02 + .word 0x1c602c02 + .word 0x1c702c02 + .word 0x1c802c02 + .word 0x1c902c02 + .word 0x1ca02c02 + .word 0x1cb02c02 + .word 0x1cc02c02 + .word 0x1cd02c02 + .word 0x1ce02c02 + .word 0x1cf02c02 + .word 0x1d002c02 + .word 0x1d102c02 + .word 0x1d202c02 + .word 0x1d302c02 + .word 0x1d402c02 + .word 0x1d502c02 + .word 0x1d602c02 + .word 0x1d702c02 + .word 0x1d802c02 + .word 0x1d902c02 + .word 0x1da02c02 + .word 0x1db02c02 + .word 0x1dc02c02 + .word 0x1dd02c02 + .word 0x1de02c02 + .word 0x1df02c02 + .word 0x1e004c02 @DDR_SHMOO_RELATED_CHANGE: change 0x1e014ca2 to 0x1e016caa to make flash code L1&L2 cachable + .word 0x1e104c02 + .word 0x1e204c02 + .word 0x1e304c02 + .word 0x1e404c02 + .word 0x1e504c02 + .word 0x1e604c02 + .word 0x1e704c02 + .word 0x1e804c0a + .word 0x1e904c0a + .word 0x1ea04c0a + .word 0x1eb04c0a + .word 0x1ec04c0a + .word 0x1ed04c0a + .word 0x1ee04c0a + .word 0x1ef04c0a + .word 0x1f004c0a + .word 0x1f104c0a + .word 0x1f204c0a + .word 0x1f304c0a + .word 0x1f404c0a + .word 0x1f504c0a + .word 0x1f604c0a + .word 0x1f704c0a + .word 0x1f804c0a + .word 0x1f904c0a + .word 0x1fa04c0a + .word 0x1fb04c0a + .word 0x1fc04c0a + .word 0x1fd04c0a + .word 0x1fe04c0a + .word 0x1ff04c0a + .word 0x20002c02 + .word 0x20102c02 + .word 0x20202c02 + .word 0x20302c02 + .word 0x20402c02 + .word 0x20502c02 + .word 0x20602c02 + .word 0x20702c02 + .word 0x20802c02 + .word 0x20902c02 + .word 0x20a02c02 + .word 0x20b02c02 + .word 0x20c02c02 + .word 0x20d02c02 + .word 0x20e02c02 + .word 0x20f02c02 + .word 0x21002c02 + .word 0x21102c02 + .word 0x21202c02 + .word 0x21302c02 + .word 0x21402c02 + .word 0x21502c02 + .word 0x21602c02 + .word 0x21702c02 + .word 0x21802c02 + .word 0x21902c02 + .word 0x21a02c02 + .word 0x21b02c02 + .word 0x21c02c02 + .word 0x21d02c02 + .word 0x21e02c02 + .word 0x21f02c02 + .word 0x22002c02 + .word 0x22102c02 + .word 0x22202c02 + .word 0x22302c02 + .word 0x22402c02 + .word 0x22502c02 + .word 0x22602c02 + .word 0x22702c02 + .word 0x22802c02 + .word 0x22902c02 + .word 0x22a02c02 + .word 0x22b02c02 + .word 0x22c02c02 + .word 0x22d02c02 + .word 0x22e02c02 + .word 0x22f02c02 + .word 0x23002c02 + .word 0x23102c02 + .word 0x23202c02 + .word 0x23302c02 + .word 0x23402c02 + .word 0x23502c02 + .word 0x23602c02 + .word 0x23702c02 + .word 0x23802c02 + .word 0x23902c02 + .word 0x23a02c02 + .word 0x23b02c02 + .word 0x23c02c02 + .word 0x23d02c02 + .word 0x23e02c02 + .word 0x23f02c02 + .word 0x24002c02 + .word 0x24102c02 + .word 0x24202c02 + .word 0x24302c02 + .word 0x24402c02 + .word 0x24502c02 + .word 0x24602c02 + .word 0x24702c02 + .word 0x24802c02 + .word 0x24902c02 + .word 0x24a02c02 + .word 0x24b02c02 + .word 0x24c02c02 + .word 0x24d02c02 + .word 0x24e02c02 + .word 0x24f02c02 + .word 0x25002c02 + .word 0x25102c02 + .word 0x25202c02 + .word 0x25302c02 + .word 0x25402c02 + .word 0x25502c02 + .word 0x25602c02 + .word 0x25702c02 + .word 0x25802c02 + .word 0x25902c02 + .word 0x25a02c02 + .word 0x25b02c02 + .word 0x25c02c02 + .word 0x25d02c02 + .word 0x25e02c02 + .word 0x25f02c02 + .word 0x26002c02 + .word 0x26102c02 + .word 0x26202c02 + .word 0x26302c02 + .word 0x26402c02 + .word 0x26502c02 + .word 0x26602c02 + .word 0x26702c02 + .word 0x26802c02 + .word 0x26902c02 + .word 0x26a02c02 + .word 0x26b02c02 + .word 0x26c02c02 + .word 0x26d02c02 + .word 0x26e02c02 + .word 0x26f02c02 + .word 0x27002c02 + .word 0x27102c02 + .word 0x27202c02 + .word 0x27302c02 + .word 0x27402c02 + .word 0x27502c02 + .word 0x27602c02 + .word 0x27702c02 + .word 0x27802c02 + .word 0x27902c02 + .word 0x27a02c02 + .word 0x27b02c02 + .word 0x27c02c02 + .word 0x27d02c02 + .word 0x27e02c02 + .word 0x27f02c02 + .word 0x28002c02 + .word 0x28102c02 + .word 0x28202c02 + .word 0x28302c02 + .word 0x28402c02 + .word 0x28502c02 + .word 0x28602c02 + .word 0x28702c02 + .word 0x28802c02 + .word 0x28902c02 + .word 0x28a02c02 + .word 0x28b02c02 + .word 0x28c02c02 + .word 0x28d02c02 + .word 0x28e02c02 + .word 0x28f02c02 + .word 0x29002c02 + .word 0x29102c02 + .word 0x29202c02 + .word 0x29302c02 + .word 0x29402c02 + .word 0x29502c02 + .word 0x29602c02 + .word 0x29702c02 + .word 0x29802c02 + .word 0x29902c02 + .word 0x29a02c02 + .word 0x29b02c02 + .word 0x29c02c02 + .word 0x29d02c02 + .word 0x29e02c02 + .word 0x29f02c02 + .word 0x2a002c02 + .word 0x2a102c02 + .word 0x2a202c02 + .word 0x2a302c02 + .word 0x2a402c02 + .word 0x2a502c02 + .word 0x2a602c02 + .word 0x2a702c02 + .word 0x2a802c02 + .word 0x2a902c02 + .word 0x2aa02c02 + .word 0x2ab02c02 + .word 0x2ac02c02 + .word 0x2ad02c02 + .word 0x2ae02c02 + .word 0x2af02c02 + .word 0x2b002c02 + .word 0x2b102c02 + .word 0x2b202c02 + .word 0x2b302c02 + .word 0x2b402c02 + .word 0x2b502c02 + .word 0x2b602c02 + .word 0x2b702c02 + .word 0x2b802c02 + .word 0x2b902c02 + .word 0x2ba02c02 + .word 0x2bb02c02 + .word 0x2bc02c02 + .word 0x2bd02c02 + .word 0x2be02c02 + .word 0x2bf02c02 + .word 0x2c002c02 + .word 0x2c102c02 + .word 0x2c202c02 + .word 0x2c302c02 + .word 0x2c402c02 + .word 0x2c502c02 + .word 0x2c602c02 + .word 0x2c702c02 + .word 0x2c802c02 + .word 0x2c902c02 + .word 0x2ca02c02 + .word 0x2cb02c02 + .word 0x2cc02c02 + .word 0x2cd02c02 + .word 0x2ce02c02 + .word 0x2cf02c02 + .word 0x2d002c02 + .word 0x2d102c02 + .word 0x2d202c02 + .word 0x2d302c02 + .word 0x2d402c02 + .word 0x2d502c02 + .word 0x2d602c02 + .word 0x2d702c02 + .word 0x2d802c02 + .word 0x2d902c02 + .word 0x2da02c02 + .word 0x2db02c02 + .word 0x2dc02c02 + .word 0x2dd02c02 + .word 0x2de02c02 + .word 0x2df02c02 + .word 0x2e002c02 + .word 0x2e102c02 + .word 0x2e202c02 + .word 0x2e302c02 + .word 0x2e402c02 + .word 0x2e502c02 + .word 0x2e602c02 + .word 0x2e702c02 + .word 0x2e802c02 + .word 0x2e902c02 + .word 0x2ea02c02 + .word 0x2eb02c02 + .word 0x2ec02c02 + .word 0x2ed02c02 + .word 0x2ee02c02 + .word 0x2ef02c02 + .word 0x2f002c02 + .word 0x2f102c02 + .word 0x2f202c02 + .word 0x2f302c02 + .word 0x2f402c02 + .word 0x2f502c02 + .word 0x2f602c02 + .word 0x2f702c02 + .word 0x2f802c02 + .word 0x2f902c02 + .word 0x2fa02c02 + .word 0x2fb02c02 + .word 0x2fc02c02 + .word 0x2fd02c02 + .word 0x2fe02c02 + .word 0x2ff02c02 + .word 0x30002c02 + .word 0x30102c02 + .word 0x30202c02 + .word 0x30302c02 + .word 0x30402c02 + .word 0x30502c02 + .word 0x30602c02 + .word 0x30702c02 + .word 0x30802c02 + .word 0x30902c02 + .word 0x30a02c02 + .word 0x30b02c02 + .word 0x30c02c02 + .word 0x30d02c02 + .word 0x30e02c02 + .word 0x30f02c02 + .word 0x31002c02 + .word 0x31102c02 + .word 0x31202c02 + .word 0x31302c02 + .word 0x31402c02 + .word 0x31502c02 + .word 0x31602c02 + .word 0x31702c02 + .word 0x31802c02 + .word 0x31902c02 + .word 0x31a02c02 + .word 0x31b02c02 + .word 0x31c02c02 + .word 0x31d02c02 + .word 0x31e02c02 + .word 0x31f02c02 + .word 0x32002c02 + .word 0x32102c02 + .word 0x32202c02 + .word 0x32302c02 + .word 0x32402c02 + .word 0x32502c02 + .word 0x32602c02 + .word 0x32702c02 + .word 0x32802c02 + .word 0x32902c02 + .word 0x32a02c02 + .word 0x32b02c02 + .word 0x32c02c02 + .word 0x32d02c02 + .word 0x32e02c02 + .word 0x32f02c02 + .word 0x33002c02 + .word 0x33102c02 + .word 0x33202c02 + .word 0x33302c02 + .word 0x33402c02 + .word 0x33502c02 + .word 0x33602c02 + .word 0x33702c02 + .word 0x33802c02 + .word 0x33902c02 + .word 0x33a02c02 + .word 0x33b02c02 + .word 0x33c02c02 + .word 0x33d02c02 + .word 0x33e02c02 + .word 0x33f02c02 + .word 0x34002c02 + .word 0x34102c02 + .word 0x34202c02 + .word 0x34302c02 + .word 0x34402c02 + .word 0x34502c02 + .word 0x34602c02 + .word 0x34702c02 + .word 0x34802c02 + .word 0x34902c02 + .word 0x34a02c02 + .word 0x34b02c02 + .word 0x34c02c02 + .word 0x34d02c02 + .word 0x34e02c02 + .word 0x34f02c02 + .word 0x35002c02 + .word 0x35102c02 + .word 0x35202c02 + .word 0x35302c02 + .word 0x35402c02 + .word 0x35502c02 + .word 0x35602c02 + .word 0x35702c02 + .word 0x35802c02 + .word 0x35902c02 + .word 0x35a02c02 + .word 0x35b02c02 + .word 0x35c02c02 + .word 0x35d02c02 + .word 0x35e02c02 + .word 0x35f02c02 + .word 0x36002c02 + .word 0x36102c02 + .word 0x36202c02 + .word 0x36302c02 + .word 0x36402c02 + .word 0x36502c02 + .word 0x36602c02 + .word 0x36702c02 + .word 0x36802c02 + .word 0x36902c02 + .word 0x36a02c02 + .word 0x36b02c02 + .word 0x36c02c02 + .word 0x36d02c02 + .word 0x36e02c02 + .word 0x36f02c02 + .word 0x37002c02 + .word 0x37102c02 + .word 0x37202c02 + .word 0x37302c02 + .word 0x37402c02 + .word 0x37502c02 + .word 0x37602c02 + .word 0x37702c02 + .word 0x37802c02 + .word 0x37902c02 + .word 0x37a02c02 + .word 0x37b02c02 + .word 0x37c02c02 + .word 0x37d02c02 + .word 0x37e02c02 + .word 0x37f02c02 + .word 0x38002c02 + .word 0x38102c02 + .word 0x38202c02 + .word 0x38302c02 + .word 0x38402c02 + .word 0x38502c02 + .word 0x38602c02 + .word 0x38702c02 + .word 0x38802c02 + .word 0x38902c02 + .word 0x38a02c02 + .word 0x38b02c02 + .word 0x38c02c02 + .word 0x38d02c02 + .word 0x38e02c02 + .word 0x38f02c02 + .word 0x39002c02 + .word 0x39102c02 + .word 0x39202c02 + .word 0x39302c02 + .word 0x39402c02 + .word 0x39502c02 + .word 0x39602c02 + .word 0x39702c02 + .word 0x39802c02 + .word 0x39902c02 + .word 0x39a02c02 + .word 0x39b02c02 + .word 0x39c02c02 + .word 0x39d02c02 + .word 0x39e02c02 + .word 0x39f02c02 + .word 0x3a002c02 + .word 0x3a102c02 + .word 0x3a202c02 + .word 0x3a302c02 + .word 0x3a402c02 + .word 0x3a502c02 + .word 0x3a602c02 + .word 0x3a702c02 + .word 0x3a802c02 + .word 0x3a902c02 + .word 0x3aa02c02 + .word 0x3ab02c02 + .word 0x3ac02c02 + .word 0x3ad02c02 + .word 0x3ae02c02 + .word 0x3af02c02 + .word 0x3b002c02 + .word 0x3b102c02 + .word 0x3b202c02 + .word 0x3b302c02 + .word 0x3b402c02 + .word 0x3b502c02 + .word 0x3b602c02 + .word 0x3b702c02 + .word 0x3b802c02 + .word 0x3b902c02 + .word 0x3ba02c02 + .word 0x3bb02c02 + .word 0x3bc02c02 + .word 0x3bd02c02 + .word 0x3be02c02 + .word 0x3bf02c02 + .word 0x3c002c02 + .word 0x3c102c02 + .word 0x3c202c02 + .word 0x3c302c02 + .word 0x3c402c02 + .word 0x3c502c02 + .word 0x3c602c02 + .word 0x3c702c02 + .word 0x3c802c02 + .word 0x3c902c02 + .word 0x3ca02c02 + .word 0x3cb02c02 + .word 0x3cc02c02 + .word 0x3cd02c02 + .word 0x3ce02c02 + .word 0x3cf02c02 + .word 0x3d002c02 + .word 0x3d102c02 + .word 0x3d202c02 + .word 0x3d302c02 + .word 0x3d402c02 + .word 0x3d502c02 + .word 0x3d602c02 + .word 0x3d702c02 + .word 0x3d802c02 + .word 0x3d902c02 + .word 0x3da02c02 + .word 0x3db02c02 + .word 0x3dc02c02 + .word 0x3dd02c02 + .word 0x3de02c02 + .word 0x3df02c02 + .word 0x3e002c02 + .word 0x3e102c02 + .word 0x3e202c02 + .word 0x3e302c02 + .word 0x3e402c02 + .word 0x3e502c02 + .word 0x3e602c02 + .word 0x3e702c02 + .word 0x3e802c02 + .word 0x3e902c02 + .word 0x3ea02c02 + .word 0x3eb02c02 + .word 0x3ec02c02 + .word 0x3ed02c02 + .word 0x3ee02c02 + .word 0x3ef02c02 + .word 0x3f002c02 + .word 0x3f102c02 + .word 0x3f202c02 + .word 0x3f302c02 + .word 0x3f402c02 + .word 0x3f502c02 + .word 0x3f602c02 + .word 0x3f702c02 + .word 0x3f802c02 + .word 0x3f902c02 + .word 0x3fa02c02 + .word 0x3fb02c02 + .word 0x3fc02c02 + .word 0x3fd02c02 + .word 0x3fe02c02 + .word 0x3ff02c02 + .word 0x40002c02 + .word 0x40102c02 + .word 0x40202c02 + .word 0x40302c02 + .word 0x40402c02 + .word 0x40502c02 + .word 0x40602c02 + .word 0x40702c02 + .word 0x40802c02 + .word 0x40902c02 + .word 0x40a02c02 + .word 0x40b02c02 + .word 0x40c02c02 + .word 0x40d02c02 + .word 0x40e02c02 + .word 0x40f02c02 + .word 0x41002c02 + .word 0x41102c02 + .word 0x41202c02 + .word 0x41302c02 + .word 0x41402c02 + .word 0x41502c02 + .word 0x41602c02 + .word 0x41702c02 + .word 0x41802c02 + .word 0x41902c02 + .word 0x41a02c02 + .word 0x41b02c02 + .word 0x41c02c02 + .word 0x41d02c02 + .word 0x41e02c02 + .word 0x41f02c02 + .word 0x42002c02 + .word 0x42102c02 + .word 0x42202c02 + .word 0x42302c02 + .word 0x42402c02 + .word 0x42502c02 + .word 0x42602c02 + .word 0x42702c02 + .word 0x42802c02 + .word 0x42902c02 + .word 0x42a02c02 + .word 0x42b02c02 + .word 0x42c02c02 + .word 0x42d02c02 + .word 0x42e02c02 + .word 0x42f02c02 + .word 0x43002c02 + .word 0x43102c02 + .word 0x43202c02 + .word 0x43302c02 + .word 0x43402c02 + .word 0x43502c02 + .word 0x43602c02 + .word 0x43702c02 + .word 0x43802c02 + .word 0x43902c02 + .word 0x43a02c02 + .word 0x43b02c02 + .word 0x43c02c02 + .word 0x43d02c02 + .word 0x43e02c02 + .word 0x43f02c02 + .word 0x44002c02 + .word 0x44102c02 + .word 0x44202c02 + .word 0x44302c02 + .word 0x44402c02 + .word 0x44502c02 + .word 0x44602c02 + .word 0x44702c02 + .word 0x44802c02 + .word 0x44902c02 + .word 0x44a02c02 + .word 0x44b02c02 + .word 0x44c02c02 + .word 0x44d02c02 + .word 0x44e02c02 + .word 0x44f02c02 + .word 0x45002c02 + .word 0x45102c02 + .word 0x45202c02 + .word 0x45302c02 + .word 0x45402c02 + .word 0x45502c02 + .word 0x45602c02 + .word 0x45702c02 + .word 0x45802c02 + .word 0x45902c02 + .word 0x45a02c02 + .word 0x45b02c02 + .word 0x45c02c02 + .word 0x45d02c02 + .word 0x45e02c02 + .word 0x45f02c02 + .word 0x46002c02 + .word 0x46102c02 + .word 0x46202c02 + .word 0x46302c02 + .word 0x46402c02 + .word 0x46502c02 + .word 0x46602c02 + .word 0x46702c02 + .word 0x46802c02 + .word 0x46902c02 + .word 0x46a02c02 + .word 0x46b02c02 + .word 0x46c02c02 + .word 0x46d02c02 + .word 0x46e02c02 + .word 0x46f02c02 + .word 0x47002c02 + .word 0x47102c02 + .word 0x47202c02 + .word 0x47302c02 + .word 0x47402c02 + .word 0x47502c02 + .word 0x47602c02 + .word 0x47702c02 + .word 0x47802c02 + .word 0x47902c02 + .word 0x47a02c02 + .word 0x47b02c02 + .word 0x47c02c02 + .word 0x47d02c02 + .word 0x47e02c02 + .word 0x47f02c02 + .word 0x48002c02 + .word 0x48102c02 + .word 0x48202c02 + .word 0x48302c02 + .word 0x48402c02 + .word 0x48502c02 + .word 0x48602c02 + .word 0x48702c02 + .word 0x48802c02 + .word 0x48902c02 + .word 0x48a02c02 + .word 0x48b02c02 + .word 0x48c02c02 + .word 0x48d02c02 + .word 0x48e02c02 + .word 0x48f02c02 + .word 0x49002c02 + .word 0x49102c02 + .word 0x49202c02 + .word 0x49302c02 + .word 0x49402c02 + .word 0x49502c02 + .word 0x49602c02 + .word 0x49702c02 + .word 0x49802c02 + .word 0x49902c02 + .word 0x49a02c02 + .word 0x49b02c02 + .word 0x49c02c02 + .word 0x49d02c02 + .word 0x49e02c02 + .word 0x49f02c02 + .word 0x4a002c02 + .word 0x4a102c02 + .word 0x4a202c02 + .word 0x4a302c02 + .word 0x4a402c02 + .word 0x4a502c02 + .word 0x4a602c02 + .word 0x4a702c02 + .word 0x4a802c02 + .word 0x4a902c02 + .word 0x4aa02c02 + .word 0x4ab02c02 + .word 0x4ac02c02 + .word 0x4ad02c02 + .word 0x4ae02c02 + .word 0x4af02c02 + .word 0x4b002c02 + .word 0x4b102c02 + .word 0x4b202c02 + .word 0x4b302c02 + .word 0x4b402c02 + .word 0x4b502c02 + .word 0x4b602c02 + .word 0x4b702c02 + .word 0x4b802c02 + .word 0x4b902c02 + .word 0x4ba02c02 + .word 0x4bb02c02 + .word 0x4bc02c02 + .word 0x4bd02c02 + .word 0x4be02c02 + .word 0x4bf02c02 + .word 0x4c002c02 + .word 0x4c102c02 + .word 0x4c202c02 + .word 0x4c302c02 + .word 0x4c402c02 + .word 0x4c502c02 + .word 0x4c602c02 + .word 0x4c702c02 + .word 0x4c802c02 + .word 0x4c902c02 + .word 0x4ca02c02 + .word 0x4cb02c02 + .word 0x4cc02c02 + .word 0x4cd02c02 + .word 0x4ce02c02 + .word 0x4cf02c02 + .word 0x4d002c02 + .word 0x4d102c02 + .word 0x4d202c02 + .word 0x4d302c02 + .word 0x4d402c02 + .word 0x4d502c02 + .word 0x4d602c02 + .word 0x4d702c02 + .word 0x4d802c02 + .word 0x4d902c02 + .word 0x4da02c02 + .word 0x4db02c02 + .word 0x4dc02c02 + .word 0x4dd02c02 + .word 0x4de02c02 + .word 0x4df02c02 + .word 0x4e002c02 + .word 0x4e102c02 + .word 0x4e202c02 + .word 0x4e302c02 + .word 0x4e402c02 + .word 0x4e502c02 + .word 0x4e602c02 + .word 0x4e702c02 + .word 0x4e802c02 + .word 0x4e902c02 + .word 0x4ea02c02 + .word 0x4eb02c02 + .word 0x4ec02c02 + .word 0x4ed02c02 + .word 0x4ee02c02 + .word 0x4ef02c02 + .word 0x4f002c02 + .word 0x4f102c02 + .word 0x4f202c02 + .word 0x4f302c02 + .word 0x4f402c02 + .word 0x4f502c02 + .word 0x4f602c02 + .word 0x4f702c02 + .word 0x4f802c02 + .word 0x4f902c02 + .word 0x4fa02c02 + .word 0x4fb02c02 + .word 0x4fc02c02 + .word 0x4fd02c02 + .word 0x4fe02c02 + .word 0x4ff02c02 + .word 0x50002c02 + .word 0x50102c02 + .word 0x50202c02 + .word 0x50302c02 + .word 0x50402c02 + .word 0x50502c02 + .word 0x50602c02 + .word 0x50702c02 + .word 0x50802c02 + .word 0x50902c02 + .word 0x50a02c02 + .word 0x50b02c02 + .word 0x50c02c02 + .word 0x50d02c02 + .word 0x50e02c02 + .word 0x50f02c02 + .word 0x51002c02 + .word 0x51102c02 + .word 0x51202c02 + .word 0x51302c02 + .word 0x51402c02 + .word 0x51502c02 + .word 0x51602c02 + .word 0x51702c02 + .word 0x51802c02 + .word 0x51902c02 + .word 0x51a02c02 + .word 0x51b02c02 + .word 0x51c02c02 + .word 0x51d02c02 + .word 0x51e02c02 + .word 0x51f02c02 + .word 0x52002c02 + .word 0x52102c02 + .word 0x52202c02 + .word 0x52302c02 + .word 0x52402c02 + .word 0x52502c02 + .word 0x52602c02 + .word 0x52702c02 + .word 0x52802c02 + .word 0x52902c02 + .word 0x52a02c02 + .word 0x52b02c02 + .word 0x52c02c02 + .word 0x52d02c02 + .word 0x52e02c02 + .word 0x52f02c02 + .word 0x53002c02 + .word 0x53102c02 + .word 0x53202c02 + .word 0x53302c02 + .word 0x53402c02 + .word 0x53502c02 + .word 0x53602c02 + .word 0x53702c02 + .word 0x53802c02 + .word 0x53902c02 + .word 0x53a02c02 + .word 0x53b02c02 + .word 0x53c02c02 + .word 0x53d02c02 + .word 0x53e02c02 + .word 0x53f02c02 + .word 0x54002c02 + .word 0x54102c02 + .word 0x54202c02 + .word 0x54302c02 + .word 0x54402c02 + .word 0x54502c02 + .word 0x54602c02 + .word 0x54702c02 + .word 0x54802c02 + .word 0x54902c02 + .word 0x54a02c02 + .word 0x54b02c02 + .word 0x54c02c02 + .word 0x54d02c02 + .word 0x54e02c02 + .word 0x54f02c02 + .word 0x55002c02 + .word 0x55102c02 + .word 0x55202c02 + .word 0x55302c02 + .word 0x55402c02 + .word 0x55502c02 + .word 0x55602c02 + .word 0x55702c02 + .word 0x55802c02 + .word 0x55902c02 + .word 0x55a02c02 + .word 0x55b02c02 + .word 0x55c02c02 + .word 0x55d02c02 + .word 0x55e02c02 + .word 0x55f02c02 + .word 0x56002c02 + .word 0x56102c02 + .word 0x56202c02 + .word 0x56302c02 + .word 0x56402c02 + .word 0x56502c02 + .word 0x56602c02 + .word 0x56702c02 + .word 0x56802c02 + .word 0x56902c02 + .word 0x56a02c02 + .word 0x56b02c02 + .word 0x56c02c02 + .word 0x56d02c02 + .word 0x56e02c02 + .word 0x56f02c02 + .word 0x57002c02 + .word 0x57102c02 + .word 0x57202c02 + .word 0x57302c02 + .word 0x57402c02 + .word 0x57502c02 + .word 0x57602c02 + .word 0x57702c02 + .word 0x57802c02 + .word 0x57902c02 + .word 0x57a02c02 + .word 0x57b02c02 + .word 0x57c02c02 + .word 0x57d02c02 + .word 0x57e02c02 + .word 0x57f02c02 + .word 0x58002c02 + .word 0x58102c02 + .word 0x58202c02 + .word 0x58302c02 + .word 0x58402c02 + .word 0x58502c02 + .word 0x58602c02 + .word 0x58702c02 + .word 0x58802c02 + .word 0x58902c02 + .word 0x58a02c02 + .word 0x58b02c02 + .word 0x58c02c02 + .word 0x58d02c02 + .word 0x58e02c02 + .word 0x58f02c02 + .word 0x59002c02 + .word 0x59102c02 + .word 0x59202c02 + .word 0x59302c02 + .word 0x59402c02 + .word 0x59502c02 + .word 0x59602c02 + .word 0x59702c02 + .word 0x59802c02 + .word 0x59902c02 + .word 0x59a02c02 + .word 0x59b02c02 + .word 0x59c02c02 + .word 0x59d02c02 + .word 0x59e02c02 + .word 0x59f02c02 + .word 0x5a002c02 + .word 0x5a102c02 + .word 0x5a202c02 + .word 0x5a302c02 + .word 0x5a402c02 + .word 0x5a502c02 + .word 0x5a602c02 + .word 0x5a702c02 + .word 0x5a802c02 + .word 0x5a902c02 + .word 0x5aa02c02 + .word 0x5ab02c02 + .word 0x5ac02c02 + .word 0x5ad02c02 + .word 0x5ae02c02 + .word 0x5af02c02 + .word 0x5b002c02 + .word 0x5b102c02 + .word 0x5b202c02 + .word 0x5b302c02 + .word 0x5b402c02 + .word 0x5b502c02 + .word 0x5b602c02 + .word 0x5b702c02 + .word 0x5b802c02 + .word 0x5b902c02 + .word 0x5ba02c02 + .word 0x5bb02c02 + .word 0x5bc02c02 + .word 0x5bd02c02 + .word 0x5be02c02 + .word 0x5bf02c02 + .word 0x5c002c02 + .word 0x5c102c02 + .word 0x5c202c02 + .word 0x5c302c02 + .word 0x5c402c02 + .word 0x5c502c02 + .word 0x5c602c02 + .word 0x5c702c02 + .word 0x5c802c02 + .word 0x5c902c02 + .word 0x5ca02c02 + .word 0x5cb02c02 + .word 0x5cc02c02 + .word 0x5cd02c02 + .word 0x5ce02c02 + .word 0x5cf02c02 + .word 0x5d002c02 + .word 0x5d102c02 + .word 0x5d202c02 + .word 0x5d302c02 + .word 0x5d402c02 + .word 0x5d502c02 + .word 0x5d602c02 + .word 0x5d702c02 + .word 0x5d802c02 + .word 0x5d902c02 + .word 0x5da02c02 + .word 0x5db02c02 + .word 0x5dc02c02 + .word 0x5dd02c02 + .word 0x5de02c02 + .word 0x5df02c02 + .word 0x5e002c02 + .word 0x5e102c02 + .word 0x5e202c02 + .word 0x5e302c02 + .word 0x5e402c02 + .word 0x5e502c02 + .word 0x5e602c02 + .word 0x5e702c02 + .word 0x5e802c02 + .word 0x5e902c02 + .word 0x5ea02c02 + .word 0x5eb02c02 + .word 0x5ec02c02 + .word 0x5ed02c02 + .word 0x5ee02c02 + .word 0x5ef02c02 + .word 0x5f002c02 + .word 0x5f102c02 + .word 0x5f202c02 + .word 0x5f302c02 + .word 0x5f402c02 + .word 0x5f502c02 + .word 0x5f602c02 + .word 0x5f702c02 + .word 0x5f802c02 + .word 0x5f902c02 + .word 0x5fa02c02 + .word 0x5fb02c02 + .word 0x5fc02c02 + .word 0x5fd02c02 + .word 0x5fe02c02 + .word 0x5ff02c02 + .word 0x60002c02 + .word 0x60102c02 + .word 0x60202c02 + .word 0x60302c02 + .word 0x60402c02 + .word 0x60502c02 + .word 0x60602c02 + .word 0x60702c02 + .word 0x60802c02 + .word 0x60902c02 + .word 0x60a02c02 + .word 0x60b02c02 + .word 0x60c02c02 + .word 0x60d02c02 + .word 0x60e02c02 + .word 0x60f02c02 + .word 0x61002c02 + .word 0x61102c02 + .word 0x61202c02 + .word 0x61302c02 + .word 0x61402c02 + .word 0x61502c02 + .word 0x61602c02 + .word 0x61702c02 + .word 0x61802c02 + .word 0x61902c02 + .word 0x61a02c02 + .word 0x61b02c02 + .word 0x61c02c02 + .word 0x61d02c02 + .word 0x61e02c02 + .word 0x61f02c02 + .word 0x62002c02 + .word 0x62102c02 + .word 0x62202c02 + .word 0x62302c02 + .word 0x62402c02 + .word 0x62502c02 + .word 0x62602c02 + .word 0x62702c02 + .word 0x62802c02 + .word 0x62902c02 + .word 0x62a02c02 + .word 0x62b02c02 + .word 0x62c02c02 + .word 0x62d02c02 + .word 0x62e02c02 + .word 0x62f02c02 + .word 0x63002c02 + .word 0x63102c02 + .word 0x63202c02 + .word 0x63302c02 + .word 0x63402c02 + .word 0x63502c02 + .word 0x63602c02 + .word 0x63702c02 + .word 0x63802c02 + .word 0x63902c02 + .word 0x63a02c02 + .word 0x63b02c02 + .word 0x63c02c02 + .word 0x63d02c02 + .word 0x63e02c02 + .word 0x63f02c02 + .word 0x64002c02 + .word 0x64102c02 + .word 0x64202c02 + .word 0x64302c02 + .word 0x64402c02 + .word 0x64502c02 + .word 0x64602c02 + .word 0x64702c02 + .word 0x64802c02 + .word 0x64902c02 + .word 0x64a02c02 + .word 0x64b02c02 + .word 0x64c02c02 + .word 0x64d02c02 + .word 0x64e02c02 + .word 0x64f02c02 + .word 0x65002c02 + .word 0x65102c02 + .word 0x65202c02 + .word 0x65302c02 + .word 0x65402c02 + .word 0x65502c02 + .word 0x65602c02 + .word 0x65702c02 + .word 0x65802c02 + .word 0x65902c02 + .word 0x65a02c02 + .word 0x65b02c02 + .word 0x65c02c02 + .word 0x65d02c02 + .word 0x65e02c02 + .word 0x65f02c02 + .word 0x66002c02 + .word 0x66102c02 + .word 0x66202c02 + .word 0x66302c02 + .word 0x66402c02 + .word 0x66502c02 + .word 0x66602c02 + .word 0x66702c02 + .word 0x66802c02 + .word 0x66902c02 + .word 0x66a02c02 + .word 0x66b02c02 + .word 0x66c02c02 + .word 0x66d02c02 + .word 0x66e02c02 + .word 0x66f02c02 + .word 0x67002c02 + .word 0x67102c02 + .word 0x67202c02 + .word 0x67302c02 + .word 0x67402c02 + .word 0x67502c02 + .word 0x67602c02 + .word 0x67702c02 + .word 0x67802c02 + .word 0x67902c02 + .word 0x67a02c02 + .word 0x67b02c02 + .word 0x67c02c02 + .word 0x67d02c02 + .word 0x67e02c02 + .word 0x67f02c02 + .word 0x68002c02 + .word 0x68102c02 + .word 0x68202c02 + .word 0x68302c02 + .word 0x68402c02 + .word 0x68502c02 + .word 0x68602c02 + .word 0x68702c02 + .word 0x68802c02 + .word 0x68902c02 + .word 0x68a02c02 + .word 0x68b02c02 + .word 0x68c02c02 + .word 0x68d02c02 + .word 0x68e02c02 + .word 0x68f02c02 + .word 0x69002c02 + .word 0x69102c02 + .word 0x69202c02 + .word 0x69302c02 + .word 0x69402c02 + .word 0x69502c02 + .word 0x69602c02 + .word 0x69702c02 + .word 0x69802c02 + .word 0x69902c02 + .word 0x69a02c02 + .word 0x69b02c02 + .word 0x69c02c02 + .word 0x69d02c02 + .word 0x69e02c02 + .word 0x69f02c02 + .word 0x6a002c02 + .word 0x6a102c02 + .word 0x6a202c02 + .word 0x6a302c02 + .word 0x6a402c02 + .word 0x6a502c02 + .word 0x6a602c02 + .word 0x6a702c02 + .word 0x6a802c02 + .word 0x6a902c02 + .word 0x6aa02c02 + .word 0x6ab02c02 + .word 0x6ac02c02 + .word 0x6ad02c02 + .word 0x6ae02c02 + .word 0x6af02c02 + .word 0x6b002c02 + .word 0x6b102c02 + .word 0x6b202c02 + .word 0x6b302c02 + .word 0x6b402c02 + .word 0x6b502c02 + .word 0x6b602c02 + .word 0x6b702c02 + .word 0x6b802c02 + .word 0x6b902c02 + .word 0x6ba02c02 + .word 0x6bb02c02 + .word 0x6bc02c02 + .word 0x6bd02c02 + .word 0x6be02c02 + .word 0x6bf02c02 + .word 0x6c002c02 + .word 0x6c102c02 + .word 0x6c202c02 + .word 0x6c302c02 + .word 0x6c402c02 + .word 0x6c502c02 + .word 0x6c602c02 + .word 0x6c702c02 + .word 0x6c802c02 + .word 0x6c902c02 + .word 0x6ca02c02 + .word 0x6cb02c02 + .word 0x6cc02c02 + .word 0x6cd02c02 + .word 0x6ce02c02 + .word 0x6cf02c02 + .word 0x6d002c02 + .word 0x6d102c02 + .word 0x6d202c02 + .word 0x6d302c02 + .word 0x6d402c02 + .word 0x6d502c02 + .word 0x6d602c02 + .word 0x6d702c02 + .word 0x6d802c02 + .word 0x6d902c02 + .word 0x6da02c02 + .word 0x6db02c02 + .word 0x6dc02c02 + .word 0x6dd02c02 + .word 0x6de02c02 + .word 0x6df02c02 + .word 0x6e002c02 + .word 0x6e102c02 + .word 0x6e202c02 + .word 0x6e302c02 + .word 0x6e402c02 + .word 0x6e502c02 + .word 0x6e602c02 + .word 0x6e702c02 + .word 0x6e802c02 + .word 0x6e902c02 + .word 0x6ea02c02 + .word 0x6eb02c02 + .word 0x6ec02c02 + .word 0x6ed02c02 + .word 0x6ee02c02 + .word 0x6ef02c02 + .word 0x6f002c02 + .word 0x6f102c02 + .word 0x6f202c02 + .word 0x6f302c02 + .word 0x6f402c02 + .word 0x6f502c02 + .word 0x6f602c02 + .word 0x6f702c02 + .word 0x6f802c02 + .word 0x6f902c02 + .word 0x6fa02c02 + .word 0x6fb02c02 + .word 0x6fc02c02 + .word 0x6fd02c02 + .word 0x6fe02c02 + .word 0x6ff02c02 + .word 0x70002c02 + .word 0x70102c02 + .word 0x70202c02 + .word 0x70302c02 + .word 0x70402c02 + .word 0x70502c02 + .word 0x70602c02 + .word 0x70702c02 + .word 0x70802c02 + .word 0x70902c02 + .word 0x70a02c02 + .word 0x70b02c02 + .word 0x70c02c02 + .word 0x70d02c02 + .word 0x70e02c02 + .word 0x70f02c02 + .word 0x71002c02 + .word 0x71102c02 + .word 0x71202c02 + .word 0x71302c02 + .word 0x71402c02 + .word 0x71502c02 + .word 0x71602c02 + .word 0x71702c02 + .word 0x71802c02 + .word 0x71902c02 + .word 0x71a02c02 + .word 0x71b02c02 + .word 0x71c02c02 + .word 0x71d02c02 + .word 0x71e02c02 + .word 0x71f02c02 + .word 0x72002c02 + .word 0x72102c02 + .word 0x72202c02 + .word 0x72302c02 + .word 0x72402c02 + .word 0x72502c02 + .word 0x72602c02 + .word 0x72702c02 + .word 0x72802c02 + .word 0x72902c02 + .word 0x72a02c02 + .word 0x72b02c02 + .word 0x72c02c02 + .word 0x72d02c02 + .word 0x72e02c02 + .word 0x72f02c02 + .word 0x73002c02 + .word 0x73102c02 + .word 0x73202c02 + .word 0x73302c02 + .word 0x73402c02 + .word 0x73502c02 + .word 0x73602c02 + .word 0x73702c02 + .word 0x73802c02 + .word 0x73902c02 + .word 0x73a02c02 + .word 0x73b02c02 + .word 0x73c02c02 + .word 0x73d02c02 + .word 0x73e02c02 + .word 0x73f02c02 + .word 0x74002c02 + .word 0x74102c02 + .word 0x74202c02 + .word 0x74302c02 + .word 0x74402c02 + .word 0x74502c02 + .word 0x74602c02 + .word 0x74702c02 + .word 0x74802c02 + .word 0x74902c02 + .word 0x74a02c02 + .word 0x74b02c02 + .word 0x74c02c02 + .word 0x74d02c02 + .word 0x74e02c02 + .word 0x74f02c02 + .word 0x75002c02 + .word 0x75102c02 + .word 0x75202c02 + .word 0x75302c02 + .word 0x75402c02 + .word 0x75502c02 + .word 0x75602c02 + .word 0x75702c02 + .word 0x75802c02 + .word 0x75902c02 + .word 0x75a02c02 + .word 0x75b02c02 + .word 0x75c02c02 + .word 0x75d02c02 + .word 0x75e02c02 + .word 0x75f02c02 + .word 0x76002c02 + .word 0x76102c02 + .word 0x76202c02 + .word 0x76302c02 + .word 0x76402c02 + .word 0x76502c02 + .word 0x76602c02 + .word 0x76702c02 + .word 0x76802c02 + .word 0x76902c02 + .word 0x76a02c02 + .word 0x76b02c02 + .word 0x76c02c02 + .word 0x76d02c02 + .word 0x76e02c02 + .word 0x76f02c02 + .word 0x77002c02 + .word 0x77102c02 + .word 0x77202c02 + .word 0x77302c02 + .word 0x77402c02 + .word 0x77502c02 + .word 0x77602c02 + .word 0x77702c02 + .word 0x77802c02 + .word 0x77902c02 + .word 0x77a02c02 + .word 0x77b02c02 + .word 0x77c02c02 + .word 0x77d02c02 + .word 0x77e02c02 + .word 0x77f02c02 + .word 0x78002c02 + .word 0x78102c02 + .word 0x78202c02 + .word 0x78302c02 + .word 0x78402c02 + .word 0x78502c02 + .word 0x78602c02 + .word 0x78702c02 + .word 0x78802c02 + .word 0x78902c02 + .word 0x78a02c02 + .word 0x78b02c02 + .word 0x78c02c02 + .word 0x78d02c02 + .word 0x78e02c02 + .word 0x78f02c02 + .word 0x79002c02 + .word 0x79102c02 + .word 0x79202c02 + .word 0x79302c02 + .word 0x79402c02 + .word 0x79502c02 + .word 0x79602c02 + .word 0x79702c02 + .word 0x79802c02 + .word 0x79902c02 + .word 0x79a02c02 + .word 0x79b02c02 + .word 0x79c02c02 + .word 0x79d02c02 + .word 0x79e02c02 + .word 0x79f02c02 + .word 0x7a002c02 + .word 0x7a102c02 + .word 0x7a202c02 + .word 0x7a302c02 + .word 0x7a402c02 + .word 0x7a502c02 + .word 0x7a602c02 + .word 0x7a702c02 + .word 0x7a802c02 + .word 0x7a902c02 + .word 0x7aa02c02 + .word 0x7ab02c02 + .word 0x7ac02c02 + .word 0x7ad02c02 + .word 0x7ae02c02 + .word 0x7af02c02 + .word 0x7b002c02 + .word 0x7b102c02 + .word 0x7b202c02 + .word 0x7b302c02 + .word 0x7b402c02 + .word 0x7b502c02 + .word 0x7b602c02 + .word 0x7b702c02 + .word 0x7b802c02 + .word 0x7b902c02 + .word 0x7ba02c02 + .word 0x7bb02c02 + .word 0x7bc02c02 + .word 0x7bd02c02 + .word 0x7be02c02 + .word 0x7bf02c02 + .word 0x7c002c02 + .word 0x7c102c02 + .word 0x7c202c02 + .word 0x7c302c02 + .word 0x7c402c02 + .word 0x7c502c02 + .word 0x7c602c02 + .word 0x7c702c02 + .word 0x7c802c02 + .word 0x7c902c02 + .word 0x7ca02c02 + .word 0x7cb02c02 + .word 0x7cc02c02 + .word 0x7cd02c02 + .word 0x7ce02c02 + .word 0x7cf02c02 + .word 0x7d002c02 + .word 0x7d102c02 + .word 0x7d202c02 + .word 0x7d302c02 + .word 0x7d402c02 + .word 0x7d502c02 + .word 0x7d602c02 + .word 0x7d702c02 + .word 0x7d802c02 + .word 0x7d902c02 + .word 0x7da02c02 + .word 0x7db02c02 + .word 0x7dc02c02 + .word 0x7dd02c02 + .word 0x7de02c02 + .word 0x7df02c02 + .word 0x7e002c02 + .word 0x7e102c02 + .word 0x7e202c02 + .word 0x7e302c02 + .word 0x7e402c02 + .word 0x7e502c02 + .word 0x7e602c02 + .word 0x7e702c02 + .word 0x7e802c02 + .word 0x7e902c02 + .word 0x7ea02c02 + .word 0x7eb02c02 + .word 0x7ec02c02 + .word 0x7ed02c02 + .word 0x7ee02c02 + .word 0x7ef02c02 + .word 0x7f002c02 + .word 0x7f102c02 + .word 0x7f202c02 + .word 0x7f302c02 + .word 0x7f402c02 + .word 0x7f502c02 + .word 0x7f602c02 + .word 0x7f702c02 + .word 0x7f802c02 + .word 0x7f902c02 + .word 0x7fa02c02 + .word 0x7fb02c02 + .word 0x7fc02c02 + .word 0x7fd02c02 + .word 0x7fe02c02 + .word 0x7ff02c02 + .word 0x80002c02 + .word 0x80102c02 + .word 0x80202c02 + .word 0x80302c02 + .word 0x80402c02 + .word 0x80502c02 + .word 0x80602c02 + .word 0x80702c02 + .word 0x80802c02 + .word 0x80902c02 + .word 0x80a02c02 + .word 0x80b02c02 + .word 0x80c02c02 + .word 0x80d02c02 + .word 0x80e02c02 + .word 0x80f02c02 + .word 0x81002c02 + .word 0x81102c02 + .word 0x81202c02 + .word 0x81302c02 + .word 0x81402c02 + .word 0x81502c02 + .word 0x81602c02 + .word 0x81702c02 + .word 0x81802c02 + .word 0x81902c02 + .word 0x81a02c02 + .word 0x81b02c02 + .word 0x81c02c02 + .word 0x81d02c02 + .word 0x81e02c02 + .word 0x81f02c02 + .word 0x82002c02 + .word 0x82102c02 + .word 0x82202c02 + .word 0x82302c02 + .word 0x82402c02 + .word 0x82502c02 + .word 0x82602c02 + .word 0x82702c02 + .word 0x82802c02 + .word 0x82902c02 + .word 0x82a02c02 + .word 0x82b02c02 + .word 0x82c02c02 + .word 0x82d02c02 + .word 0x82e02c02 + .word 0x82f02c02 + .word 0x83002c02 + .word 0x83102c02 + .word 0x83202c02 + .word 0x83302c02 + .word 0x83402c02 + .word 0x83502c02 + .word 0x83602c02 + .word 0x83702c02 + .word 0x83802c02 + .word 0x83902c02 + .word 0x83a02c02 + .word 0x83b02c02 + .word 0x83c02c02 + .word 0x83d02c02 + .word 0x83e02c02 + .word 0x83f02c02 + .word 0x84002c02 + .word 0x84102c02 + .word 0x84202c02 + .word 0x84302c02 + .word 0x84402c02 + .word 0x84502c02 + .word 0x84602c02 + .word 0x84702c02 + .word 0x84802c02 + .word 0x84902c02 + .word 0x84a02c02 + .word 0x84b02c02 + .word 0x84c02c02 + .word 0x84d02c02 + .word 0x84e02c02 + .word 0x84f02c02 + .word 0x85002c02 + .word 0x85102c02 + .word 0x85202c02 + .word 0x85302c02 + .word 0x85402c02 + .word 0x85502c02 + .word 0x85602c02 + .word 0x85702c02 + .word 0x85802c02 + .word 0x85902c02 + .word 0x85a02c02 + .word 0x85b02c02 + .word 0x85c02c02 + .word 0x85d02c02 + .word 0x85e02c02 + .word 0x85f02c02 + .word 0x86002c02 + .word 0x86102c02 + .word 0x86202c02 + .word 0x86302c02 + .word 0x86402c02 + .word 0x86502c02 + .word 0x86602c02 + .word 0x86702c02 + .word 0x86802c02 + .word 0x86902c02 + .word 0x86a02c02 + .word 0x86b02c02 + .word 0x86c02c02 + .word 0x86d02c02 + .word 0x86e02c02 + .word 0x86f02c02 + .word 0x87002c02 + .word 0x87102c02 + .word 0x87202c02 + .word 0x87302c02 + .word 0x87402c02 + .word 0x87502c02 + .word 0x87602c02 + .word 0x87702c02 + .word 0x87802c02 + .word 0x87902c02 + .word 0x87a02c02 + .word 0x87b02c02 + .word 0x87c02c02 + .word 0x87d02c02 + .word 0x87e02c02 + .word 0x87f02c02 + .word 0x88002c02 + .word 0x88102c02 + .word 0x88202c02 + .word 0x88302c02 + .word 0x88402c02 + .word 0x88502c02 + .word 0x88602c02 + .word 0x88702c02 + .word 0x88802c02 + .word 0x88902c02 + .word 0x88a02c02 + .word 0x88b02c02 + .word 0x88c02c02 + .word 0x88d02c02 + .word 0x88e02c02 + .word 0x88f02c02 + .word 0x89002c02 + .word 0x89102c02 + .word 0x89202c02 + .word 0x89302c02 + .word 0x89402c02 + .word 0x89502c02 + .word 0x89602c02 + .word 0x89702c02 + .word 0x89802c02 + .word 0x89902c02 + .word 0x89a02c02 + .word 0x89b02c02 + .word 0x89c02c02 + .word 0x89d02c02 + .word 0x89e02c02 + .word 0x89f02c02 + .word 0x8a002c02 + .word 0x8a102c02 + .word 0x8a202c02 + .word 0x8a302c02 + .word 0x8a402c02 + .word 0x8a502c02 + .word 0x8a602c02 + .word 0x8a702c02 + .word 0x8a802c02 + .word 0x8a902c02 + .word 0x8aa02c02 + .word 0x8ab02c02 + .word 0x8ac02c02 + .word 0x8ad02c02 + .word 0x8ae02c02 + .word 0x8af02c02 + .word 0x8b002c02 + .word 0x8b102c02 + .word 0x8b202c02 + .word 0x8b302c02 + .word 0x8b402c02 + .word 0x8b502c02 + .word 0x8b602c02 + .word 0x8b702c02 + .word 0x8b802c02 + .word 0x8b902c02 + .word 0x8ba02c02 + .word 0x8bb02c02 + .word 0x8bc02c02 + .word 0x8bd02c02 + .word 0x8be02c02 + .word 0x8bf02c02 + .word 0x8c002c02 + .word 0x8c102c02 + .word 0x8c202c02 + .word 0x8c302c02 + .word 0x8c402c02 + .word 0x8c502c02 + .word 0x8c602c02 + .word 0x8c702c02 + .word 0x8c802c02 + .word 0x8c902c02 + .word 0x8ca02c02 + .word 0x8cb02c02 + .word 0x8cc02c02 + .word 0x8cd02c02 + .word 0x8ce02c02 + .word 0x8cf02c02 + .word 0x8d002c02 + .word 0x8d102c02 + .word 0x8d202c02 + .word 0x8d302c02 + .word 0x8d402c02 + .word 0x8d502c02 + .word 0x8d602c02 + .word 0x8d702c02 + .word 0x8d802c02 + .word 0x8d902c02 + .word 0x8da02c02 + .word 0x8db02c02 + .word 0x8dc02c02 + .word 0x8dd02c02 + .word 0x8de02c02 + .word 0x8df02c02 + .word 0x8e002c02 + .word 0x8e102c02 + .word 0x8e202c02 + .word 0x8e302c02 + .word 0x8e402c02 + .word 0x8e502c02 + .word 0x8e602c02 + .word 0x8e702c02 + .word 0x8e802c02 + .word 0x8e902c02 + .word 0x8ea02c02 + .word 0x8eb02c02 + .word 0x8ec02c02 + .word 0x8ed02c02 + .word 0x8ee02c02 + .word 0x8ef02c02 + .word 0x8f002c02 + .word 0x8f102c02 + .word 0x8f202c02 + .word 0x8f302c02 + .word 0x8f402c02 + .word 0x8f502c02 + .word 0x8f602c02 + .word 0x8f702c02 + .word 0x8f802c02 + .word 0x8f902c02 + .word 0x8fa02c02 + .word 0x8fb02c02 + .word 0x8fc02c02 + .word 0x8fd02c02 + .word 0x8fe02c02 + .word 0x8ff02c02 + .word 0x90002c02 + .word 0x90102c02 + .word 0x90202c02 + .word 0x90302c02 + .word 0x90402c02 + .word 0x90502c02 + .word 0x90602c02 + .word 0x90702c02 + .word 0x90802c02 + .word 0x90902c02 + .word 0x90a02c02 + .word 0x90b02c02 + .word 0x90c02c02 + .word 0x90d02c02 + .word 0x90e02c02 + .word 0x90f02c02 + .word 0x91002c02 + .word 0x91102c02 + .word 0x91202c02 + .word 0x91302c02 + .word 0x91402c02 + .word 0x91502c02 + .word 0x91602c02 + .word 0x91702c02 + .word 0x91802c02 + .word 0x91902c02 + .word 0x91a02c02 + .word 0x91b02c02 + .word 0x91c02c02 + .word 0x91d02c02 + .word 0x91e02c02 + .word 0x91f02c02 + .word 0x92002c02 + .word 0x92102c02 + .word 0x92202c02 + .word 0x92302c02 + .word 0x92402c02 + .word 0x92502c02 + .word 0x92602c02 + .word 0x92702c02 + .word 0x92802c02 + .word 0x92902c02 + .word 0x92a02c02 + .word 0x92b02c02 + .word 0x92c02c02 + .word 0x92d02c02 + .word 0x92e02c02 + .word 0x92f02c02 + .word 0x93002c02 + .word 0x93102c02 + .word 0x93202c02 + .word 0x93302c02 + .word 0x93402c02 + .word 0x93502c02 + .word 0x93602c02 + .word 0x93702c02 + .word 0x93802c02 + .word 0x93902c02 + .word 0x93a02c02 + .word 0x93b02c02 + .word 0x93c02c02 + .word 0x93d02c02 + .word 0x93e02c02 + .word 0x93f02c02 + .word 0x94002c02 + .word 0x94102c02 + .word 0x94202c02 + .word 0x94302c02 + .word 0x94402c02 + .word 0x94502c02 + .word 0x94602c02 + .word 0x94702c02 + .word 0x94802c02 + .word 0x94902c02 + .word 0x94a02c02 + .word 0x94b02c02 + .word 0x94c02c02 + .word 0x94d02c02 + .word 0x94e02c02 + .word 0x94f02c02 + .word 0x95002c02 + .word 0x95102c02 + .word 0x95202c02 + .word 0x95302c02 + .word 0x95402c02 + .word 0x95502c02 + .word 0x95602c02 + .word 0x95702c02 + .word 0x95802c02 + .word 0x95902c02 + .word 0x95a02c02 + .word 0x95b02c02 + .word 0x95c02c02 + .word 0x95d02c02 + .word 0x95e02c02 + .word 0x95f02c02 + .word 0x96002c02 + .word 0x96102c02 + .word 0x96202c02 + .word 0x96302c02 + .word 0x96402c02 + .word 0x96502c02 + .word 0x96602c02 + .word 0x96702c02 + .word 0x96802c02 + .word 0x96902c02 + .word 0x96a02c02 + .word 0x96b02c02 + .word 0x96c02c02 + .word 0x96d02c02 + .word 0x96e02c02 + .word 0x96f02c02 + .word 0x97002c02 + .word 0x97102c02 + .word 0x97202c02 + .word 0x97302c02 + .word 0x97402c02 + .word 0x97502c02 + .word 0x97602c02 + .word 0x97702c02 + .word 0x97802c02 + .word 0x97902c02 + .word 0x97a02c02 + .word 0x97b02c02 + .word 0x97c02c02 + .word 0x97d02c02 + .word 0x97e02c02 + .word 0x97f02c02 + .word 0x98002c02 + .word 0x98102c02 + .word 0x98202c02 + .word 0x98302c02 + .word 0x98402c02 + .word 0x98502c02 + .word 0x98602c02 + .word 0x98702c02 + .word 0x98802c02 + .word 0x98902c02 + .word 0x98a02c02 + .word 0x98b02c02 + .word 0x98c02c02 + .word 0x98d02c02 + .word 0x98e02c02 + .word 0x98f02c02 + .word 0x99002c02 + .word 0x99102c02 + .word 0x99202c02 + .word 0x99302c02 + .word 0x99402c02 + .word 0x99502c02 + .word 0x99602c02 + .word 0x99702c02 + .word 0x99802c02 + .word 0x99902c02 + .word 0x99a02c02 + .word 0x99b02c02 + .word 0x99c02c02 + .word 0x99d02c02 + .word 0x99e02c02 + .word 0x99f02c02 + .word 0x9a002c02 + .word 0x9a102c02 + .word 0x9a202c02 + .word 0x9a302c02 + .word 0x9a402c02 + .word 0x9a502c02 + .word 0x9a602c02 + .word 0x9a702c02 + .word 0x9a802c02 + .word 0x9a902c02 + .word 0x9aa02c02 + .word 0x9ab02c02 + .word 0x9ac02c02 + .word 0x9ad02c02 + .word 0x9ae02c02 + .word 0x9af02c02 + .word 0x9b002c02 + .word 0x9b102c02 + .word 0x9b202c02 + .word 0x9b302c02 + .word 0x9b402c02 + .word 0x9b502c02 + .word 0x9b602c02 + .word 0x9b702c02 + .word 0x9b802c02 + .word 0x9b902c02 + .word 0x9ba02c02 + .word 0x9bb02c02 + .word 0x9bc02c02 + .word 0x9bd02c02 + .word 0x9be02c02 + .word 0x9bf02c02 + .word 0x9c002c02 + .word 0x9c102c02 + .word 0x9c202c02 + .word 0x9c302c02 + .word 0x9c402c02 + .word 0x9c502c02 + .word 0x9c602c02 + .word 0x9c702c02 + .word 0x9c802c02 + .word 0x9c902c02 + .word 0x9ca02c02 + .word 0x9cb02c02 + .word 0x9cc02c02 + .word 0x9cd02c02 + .word 0x9ce02c02 + .word 0x9cf02c02 + .word 0x9d002c02 + .word 0x9d102c02 + .word 0x9d202c02 + .word 0x9d302c02 + .word 0x9d402c02 + .word 0x9d502c02 + .word 0x9d602c02 + .word 0x9d702c02 + .word 0x9d802c02 + .word 0x9d902c02 + .word 0x9da02c02 + .word 0x9db02c02 + .word 0x9dc02c02 + .word 0x9dd02c02 + .word 0x9de02c02 + .word 0x9df02c02 + .word 0x9e002c02 + .word 0x9e102c02 + .word 0x9e202c02 + .word 0x9e302c02 + .word 0x9e402c02 + .word 0x9e502c02 + .word 0x9e602c02 + .word 0x9e702c02 + .word 0x9e802c02 + .word 0x9e902c02 + .word 0x9ea02c02 + .word 0x9eb02c02 + .word 0x9ec02c02 + .word 0x9ed02c02 + .word 0x9ee02c02 + .word 0x9ef02c02 + .word 0x9f002c02 + .word 0x9f102c02 + .word 0x9f202c02 + .word 0x9f302c02 + .word 0x9f402c02 + .word 0x9f502c02 + .word 0x9f602c02 + .word 0x9f702c02 + .word 0x9f802c02 + .word 0x9f902c02 + .word 0x9fa02c02 + .word 0x9fb02c02 + .word 0x9fc02c02 + .word 0x9fd02c02 + .word 0x9fe02c02 + .word 0x9ff02c02 + .word 0xa0002c02 + .word 0xa0102c02 + .word 0xa0202c02 + .word 0xa0302c02 + .word 0xa0402c02 + .word 0xa0502c02 + .word 0xa0602c02 + .word 0xa0702c02 + .word 0xa0802c02 + .word 0xa0902c02 + .word 0xa0a02c02 + .word 0xa0b02c02 + .word 0xa0c02c02 + .word 0xa0d02c02 + .word 0xa0e02c02 + .word 0xa0f02c02 + .word 0xa1002c02 + .word 0xa1102c02 + .word 0xa1202c02 + .word 0xa1302c02 + .word 0xa1402c02 + .word 0xa1502c02 + .word 0xa1602c02 + .word 0xa1702c02 + .word 0xa1802c02 + .word 0xa1902c02 + .word 0xa1a02c02 + .word 0xa1b02c02 + .word 0xa1c02c02 + .word 0xa1d02c02 + .word 0xa1e02c02 + .word 0xa1f02c02 + .word 0xa2002c02 + .word 0xa2102c02 + .word 0xa2202c02 + .word 0xa2302c02 + .word 0xa2402c02 + .word 0xa2502c02 + .word 0xa2602c02 + .word 0xa2702c02 + .word 0xa2802c02 + .word 0xa2902c02 + .word 0xa2a02c02 + .word 0xa2b02c02 + .word 0xa2c02c02 + .word 0xa2d02c02 + .word 0xa2e02c02 + .word 0xa2f02c02 + .word 0xa3002c02 + .word 0xa3102c02 + .word 0xa3202c02 + .word 0xa3302c02 + .word 0xa3402c02 + .word 0xa3502c02 + .word 0xa3602c02 + .word 0xa3702c02 + .word 0xa3802c02 + .word 0xa3902c02 + .word 0xa3a02c02 + .word 0xa3b02c02 + .word 0xa3c02c02 + .word 0xa3d02c02 + .word 0xa3e02c02 + .word 0xa3f02c02 + .word 0xa4002c02 + .word 0xa4102c02 + .word 0xa4202c02 + .word 0xa4302c02 + .word 0xa4402c02 + .word 0xa4502c02 + .word 0xa4602c02 + .word 0xa4702c02 + .word 0xa4802c02 + .word 0xa4902c02 + .word 0xa4a02c02 + .word 0xa4b02c02 + .word 0xa4c02c02 + .word 0xa4d02c02 + .word 0xa4e02c02 + .word 0xa4f02c02 + .word 0xa5002c02 + .word 0xa5102c02 + .word 0xa5202c02 + .word 0xa5302c02 + .word 0xa5402c02 + .word 0xa5502c02 + .word 0xa5602c02 + .word 0xa5702c02 + .word 0xa5802c02 + .word 0xa5902c02 + .word 0xa5a02c02 + .word 0xa5b02c02 + .word 0xa5c02c02 + .word 0xa5d02c02 + .word 0xa5e02c02 + .word 0xa5f02c02 + .word 0xa6002c02 + .word 0xa6102c02 + .word 0xa6202c02 + .word 0xa6302c02 + .word 0xa6402c02 + .word 0xa6502c02 + .word 0xa6602c02 + .word 0xa6702c02 + .word 0xa6802c02 + .word 0xa6902c02 + .word 0xa6a02c02 + .word 0xa6b02c02 + .word 0xa6c02c02 + .word 0xa6d02c02 + .word 0xa6e02c02 + .word 0xa6f02c02 + .word 0xa7002c02 + .word 0xa7102c02 + .word 0xa7202c02 + .word 0xa7302c02 + .word 0xa7402c02 + .word 0xa7502c02 + .word 0xa7602c02 + .word 0xa7702c02 + .word 0xa7802c02 + .word 0xa7902c02 + .word 0xa7a02c02 + .word 0xa7b02c02 + .word 0xa7c02c02 + .word 0xa7d02c02 + .word 0xa7e02c02 + .word 0xa7f02c02 + .word 0xa8002c02 + .word 0xa8102c02 + .word 0xa8202c02 + .word 0xa8302c02 + .word 0xa8402c02 + .word 0xa8502c02 + .word 0xa8602c02 + .word 0xa8702c02 + .word 0xa8802c02 + .word 0xa8902c02 + .word 0xa8a02c02 + .word 0xa8b02c02 + .word 0xa8c02c02 + .word 0xa8d02c02 + .word 0xa8e02c02 + .word 0xa8f02c02 + .word 0xa9002c02 + .word 0xa9102c02 + .word 0xa9202c02 + .word 0xa9302c02 + .word 0xa9402c02 + .word 0xa9502c02 + .word 0xa9602c02 + .word 0xa9702c02 + .word 0xa9802c02 + .word 0xa9902c02 + .word 0xa9a02c02 + .word 0xa9b02c02 + .word 0xa9c02c02 + .word 0xa9d02c02 + .word 0xa9e02c02 + .word 0xa9f02c02 + .word 0xaa002c02 + .word 0xaa102c02 + .word 0xaa202c02 + .word 0xaa302c02 + .word 0xaa402c02 + .word 0xaa502c02 + .word 0xaa602c02 + .word 0xaa702c02 + .word 0xaa802c02 + .word 0xaa902c02 + .word 0xaaa02c02 + .word 0xaab02c02 + .word 0xaac02c02 + .word 0xaad02c02 + .word 0xaae02c02 + .word 0xaaf02c02 + .word 0xab002c02 + .word 0xab102c02 + .word 0xab202c02 + .word 0xab302c02 + .word 0xab402c02 + .word 0xab502c02 + .word 0xab602c02 + .word 0xab702c02 + .word 0xab802c02 + .word 0xab902c02 + .word 0xaba02c02 + .word 0xabb02c02 + .word 0xabc02c02 + .word 0xabd02c02 + .word 0xabe02c02 + .word 0xabf02c02 + .word 0xac002c02 + .word 0xac102c02 + .word 0xac202c02 + .word 0xac302c02 + .word 0xac402c02 + .word 0xac502c02 + .word 0xac602c02 + .word 0xac702c02 + .word 0xac802c02 + .word 0xac902c02 + .word 0xaca02c02 + .word 0xacb02c02 + .word 0xacc02c02 + .word 0xacd02c02 + .word 0xace02c02 + .word 0xacf02c02 + .word 0xad002c02 + .word 0xad102c02 + .word 0xad202c02 + .word 0xad302c02 + .word 0xad402c02 + .word 0xad502c02 + .word 0xad602c02 + .word 0xad702c02 + .word 0xad802c02 + .word 0xad902c02 + .word 0xada02c02 + .word 0xadb02c02 + .word 0xadc02c02 + .word 0xadd02c02 + .word 0xade02c02 + .word 0xadf02c02 + .word 0xae002c02 + .word 0xae102c02 + .word 0xae202c02 + .word 0xae302c02 + .word 0xae402c02 + .word 0xae502c02 + .word 0xae602c02 + .word 0xae702c02 + .word 0xae802c02 + .word 0xae902c02 + .word 0xaea02c02 + .word 0xaeb02c02 + .word 0xaec02c02 + .word 0xaed02c02 + .word 0xaee02c02 + .word 0xaef02c02 + .word 0xaf002c02 + .word 0xaf102c02 + .word 0xaf202c02 + .word 0xaf302c02 + .word 0xaf402c02 + .word 0xaf502c02 + .word 0xaf602c02 + .word 0xaf702c02 + .word 0xaf802c02 + .word 0xaf902c02 + .word 0xafa02c02 + .word 0xafb02c02 + .word 0xafc02c02 + .word 0xafd02c02 + .word 0xafe02c02 + .word 0xaff02c02 + .word 0xb0002c02 + .word 0xb0102c02 + .word 0xb0202c02 + .word 0xb0302c02 + .word 0xb0402c02 + .word 0xb0502c02 + .word 0xb0602c02 + .word 0xb0702c02 + .word 0xb0802c02 + .word 0xb0902c02 + .word 0xb0a02c02 + .word 0xb0b02c02 + .word 0xb0c02c02 + .word 0xb0d02c02 + .word 0xb0e02c02 + .word 0xb0f02c02 + .word 0xb1002c02 + .word 0xb1102c02 + .word 0xb1202c02 + .word 0xb1302c02 + .word 0xb1402c02 + .word 0xb1502c02 + .word 0xb1602c02 + .word 0xb1702c02 + .word 0xb1802c02 + .word 0xb1902c02 + .word 0xb1a02c02 + .word 0xb1b02c02 + .word 0xb1c02c02 + .word 0xb1d02c02 + .word 0xb1e02c02 + .word 0xb1f02c02 + .word 0xb2002c02 + .word 0xb2102c02 + .word 0xb2202c02 + .word 0xb2302c02 + .word 0xb2402c02 + .word 0xb2502c02 + .word 0xb2602c02 + .word 0xb2702c02 + .word 0xb2802c02 + .word 0xb2902c02 + .word 0xb2a02c02 + .word 0xb2b02c02 + .word 0xb2c02c02 + .word 0xb2d02c02 + .word 0xb2e02c02 + .word 0xb2f02c02 + .word 0xb3002c02 + .word 0xb3102c02 + .word 0xb3202c02 + .word 0xb3302c02 + .word 0xb3402c02 + .word 0xb3502c02 + .word 0xb3602c02 + .word 0xb3702c02 + .word 0xb3802c02 + .word 0xb3902c02 + .word 0xb3a02c02 + .word 0xb3b02c02 + .word 0xb3c02c02 + .word 0xb3d02c02 + .word 0xb3e02c02 + .word 0xb3f02c02 + .word 0xb4002c02 + .word 0xb4102c02 + .word 0xb4202c02 + .word 0xb4302c02 + .word 0xb4402c02 + .word 0xb4502c02 + .word 0xb4602c02 + .word 0xb4702c02 + .word 0xb4802c02 + .word 0xb4902c02 + .word 0xb4a02c02 + .word 0xb4b02c02 + .word 0xb4c02c02 + .word 0xb4d02c02 + .word 0xb4e02c02 + .word 0xb4f02c02 + .word 0xb5002c02 + .word 0xb5102c02 + .word 0xb5202c02 + .word 0xb5302c02 + .word 0xb5402c02 + .word 0xb5502c02 + .word 0xb5602c02 + .word 0xb5702c02 + .word 0xb5802c02 + .word 0xb5902c02 + .word 0xb5a02c02 + .word 0xb5b02c02 + .word 0xb5c02c02 + .word 0xb5d02c02 + .word 0xb5e02c02 + .word 0xb5f02c02 + .word 0xb6002c02 + .word 0xb6102c02 + .word 0xb6202c02 + .word 0xb6302c02 + .word 0xb6402c02 + .word 0xb6502c02 + .word 0xb6602c02 + .word 0xb6702c02 + .word 0xb6802c02 + .word 0xb6902c02 + .word 0xb6a02c02 + .word 0xb6b02c02 + .word 0xb6c02c02 + .word 0xb6d02c02 + .word 0xb6e02c02 + .word 0xb6f02c02 + .word 0xb7002c02 + .word 0xb7102c02 + .word 0xb7202c02 + .word 0xb7302c02 + .word 0xb7402c02 + .word 0xb7502c02 + .word 0xb7602c02 + .word 0xb7702c02 + .word 0xb7802c02 + .word 0xb7902c02 + .word 0xb7a02c02 + .word 0xb7b02c02 + .word 0xb7c02c02 + .word 0xb7d02c02 + .word 0xb7e02c02 + .word 0xb7f02c02 + .word 0xb8002c02 + .word 0xb8102c02 + .word 0xb8202c02 + .word 0xb8302c02 + .word 0xb8402c02 + .word 0xb8502c02 + .word 0xb8602c02 + .word 0xb8702c02 + .word 0xb8802c02 + .word 0xb8902c02 + .word 0xb8a02c02 + .word 0xb8b02c02 + .word 0xb8c02c02 + .word 0xb8d02c02 + .word 0xb8e02c02 + .word 0xb8f02c02 + .word 0xb9002c02 + .word 0xb9102c02 + .word 0xb9202c02 + .word 0xb9302c02 + .word 0xb9402c02 + .word 0xb9502c02 + .word 0xb9602c02 + .word 0xb9702c02 + .word 0xb9802c02 + .word 0xb9902c02 + .word 0xb9a02c02 + .word 0xb9b02c02 + .word 0xb9c02c02 + .word 0xb9d02c02 + .word 0xb9e02c02 + .word 0xb9f02c02 + .word 0xba002c02 + .word 0xba102c02 + .word 0xba202c02 + .word 0xba302c02 + .word 0xba402c02 + .word 0xba502c02 + .word 0xba602c02 + .word 0xba702c02 + .word 0xba802c02 + .word 0xba902c02 + .word 0xbaa02c02 + .word 0xbab02c02 + .word 0xbac02c02 + .word 0xbad02c02 + .word 0xbae02c02 + .word 0xbaf02c02 + .word 0xbb002c02 + .word 0xbb102c02 + .word 0xbb202c02 + .word 0xbb302c02 + .word 0xbb402c02 + .word 0xbb502c02 + .word 0xbb602c02 + .word 0xbb702c02 + .word 0xbb802c02 + .word 0xbb902c02 + .word 0xbba02c02 + .word 0xbbb02c02 + .word 0xbbc02c02 + .word 0xbbd02c02 + .word 0xbbe02c02 + .word 0xbbf02c02 + .word 0xbc002c02 + .word 0xbc102c02 + .word 0xbc202c02 + .word 0xbc302c02 + .word 0xbc402c02 + .word 0xbc502c02 + .word 0xbc602c02 + .word 0xbc702c02 + .word 0xbc802c02 + .word 0xbc902c02 + .word 0xbca02c02 + .word 0xbcb02c02 + .word 0xbcc02c02 + .word 0xbcd02c02 + .word 0xbce02c02 + .word 0xbcf02c02 + .word 0xbd002c02 + .word 0xbd102c02 + .word 0xbd202c02 + .word 0xbd302c02 + .word 0xbd402c02 + .word 0xbd502c02 + .word 0xbd602c02 + .word 0xbd702c02 + .word 0xbd802c02 + .word 0xbd902c02 + .word 0xbda02c02 + .word 0xbdb02c02 + .word 0xbdc02c02 + .word 0xbdd02c02 + .word 0xbde02c02 + .word 0xbdf02c02 + .word 0xbe002c02 + .word 0xbe102c02 + .word 0xbe202c02 + .word 0xbe302c02 + .word 0xbe402c02 + .word 0xbe502c02 + .word 0xbe602c02 + .word 0xbe702c02 + .word 0xbe802c02 + .word 0xbe902c02 + .word 0xbea02c02 + .word 0xbeb02c02 + .word 0xbec02c02 + .word 0xbed02c02 + .word 0xbee02c02 + .word 0xbef02c02 + .word 0xbf002c02 + .word 0xbf102c02 + .word 0xbf202c02 + .word 0xbf302c02 + .word 0xbf402c02 + .word 0xbf502c02 + .word 0xbf602c02 + .word 0xbf702c02 + .word 0xbf802c02 + .word 0xbf902c02 + .word 0xbfa02c02 + .word 0xbfb02c02 + .word 0xbfc02c02 + .word 0xbfd02c02 + .word 0xbfe02c02 + .word 0xbff02c02 + .word 0xc0015ca2 + .word 0xc0102c02 + .word 0xc0202c02 + .word 0xc0302c02 + .word 0xc0402c02 + .word 0xc0502c02 + .word 0xc0602c02 + .word 0xc0702c02 + .word 0xc0802c02 + .word 0xc0902c02 + .word 0xc0a02c02 + .word 0xc0b02c02 + .word 0xc0c02c02 + .word 0xc0d02c02 + .word 0xc0e02c02 + .word 0xc0f02c02 + .word 0xc1002c02 + .word 0xc1102c02 + .word 0xc1202c02 + .word 0xc1302c02 + .word 0xc1402c02 + .word 0xc1502c02 + .word 0xc1602c02 + .word 0xc1702c02 + .word 0xc1802c02 + .word 0xc1902c02 + .word 0xc1a02c02 + .word 0xc1b02c02 + .word 0xc1c02c02 + .word 0xc1d02c02 + .word 0xc1e02c02 + .word 0xc1f02c02 + .word 0xc2002c02 + .word 0xc2102c02 + .word 0xc2202c02 + .word 0xc2302c02 + .word 0xc2402c02 + .word 0xc2502c02 + .word 0xc2602c02 + .word 0xc2702c02 + .word 0xc2802c02 + .word 0xc2902c02 + .word 0xc2a02c02 + .word 0xc2b02c02 + .word 0xc2c02c02 + .word 0xc2d02c02 + .word 0xc2e02c02 + .word 0xc2f02c02 + .word 0xc3002c02 + .word 0xc3102c02 + .word 0xc3202c02 + .word 0xc3302c02 + .word 0xc3402c02 + .word 0xc3502c02 + .word 0xc3602c02 + .word 0xc3702c02 + .word 0xc3802c02 + .word 0xc3902c02 + .word 0xc3a02c02 + .word 0xc3b02c02 + .word 0xc3c02c02 + .word 0xc3d02c02 + .word 0xc3e02c02 + .word 0xc3f02c02 + .word 0xc4002c02 + .word 0xc4102c02 + .word 0xc4202c02 + .word 0xc4302c02 + .word 0xc4402c02 + .word 0xc4502c02 + .word 0xc4602c02 + .word 0xc4702c02 + .word 0xc4802c02 + .word 0xc4902c02 + .word 0xc4a02c02 + .word 0xc4b02c02 + .word 0xc4c02c02 + .word 0xc4d02c02 + .word 0xc4e02c02 + .word 0xc4f02c02 + .word 0xc5002c02 + .word 0xc5102c02 + .word 0xc5202c02 + .word 0xc5302c02 + .word 0xc5402c02 + .word 0xc5502c02 + .word 0xc5602c02 + .word 0xc5702c02 + .word 0xc5802c02 + .word 0xc5902c02 + .word 0xc5a02c02 + .word 0xc5b02c02 + .word 0xc5c02c02 + .word 0xc5d02c02 + .word 0xc5e02c02 + .word 0xc5f02c02 + .word 0xc6002c02 + .word 0xc6102c02 + .word 0xc6202c02 + .word 0xc6302c02 + .word 0xc6402c02 + .word 0xc6502c02 + .word 0xc6602c02 + .word 0xc6702c02 + .word 0xc6802c02 + .word 0xc6902c02 + .word 0xc6a02c02 + .word 0xc6b02c02 + .word 0xc6c02c02 + .word 0xc6d02c02 + .word 0xc6e02c02 + .word 0xc6f02c02 + .word 0xc7002c02 + .word 0xc7102c02 + .word 0xc7202c02 + .word 0xc7302c02 + .word 0xc7402c02 + .word 0xc7502c02 + .word 0xc7602c02 + .word 0xc7702c02 + .word 0xc7802c02 + .word 0xc7902c02 + .word 0xc7a02c02 + .word 0xc7b02c02 + .word 0xc7c02c02 + .word 0xc7d02c02 + .word 0xc7e02c02 + .word 0xc7f02c02 + .word 0xc8002c02 + .word 0xc8102c02 + .word 0xc8202c02 + .word 0xc8302c02 + .word 0xc8402c02 + .word 0xc8502c02 + .word 0xc8602c02 + .word 0xc8702c02 + .word 0xc8802c02 + .word 0xc8902c02 + .word 0xc8a02c02 + .word 0xc8b02c02 + .word 0xc8c02c02 + .word 0xc8d02c02 + .word 0xc8e02c02 + .word 0xc8f02c02 + .word 0xc9002c02 + .word 0xc9102c02 + .word 0xc9202c02 + .word 0xc9302c02 + .word 0xc9402c02 + .word 0xc9502c02 + .word 0xc9602c02 + .word 0xc9702c02 + .word 0xc9802c02 + .word 0xc9902c02 + .word 0xc9a02c02 + .word 0xc9b02c02 + .word 0xc9c02c02 + .word 0xc9d02c02 + .word 0xc9e02c02 + .word 0xc9f02c02 + .word 0xca002c02 + .word 0xca102c02 + .word 0xca202c02 + .word 0xca302c02 + .word 0xca402c02 + .word 0xca502c02 + .word 0xca602c02 + .word 0xca702c02 + .word 0xca802c02 + .word 0xca902c02 + .word 0xcaa02c02 + .word 0xcab02c02 + .word 0xcac02c02 + .word 0xcad02c02 + .word 0xcae02c02 + .word 0xcaf02c02 + .word 0xcb002c02 + .word 0xcb102c02 + .word 0xcb202c02 + .word 0xcb302c02 + .word 0xcb402c02 + .word 0xcb502c02 + .word 0xcb602c02 + .word 0xcb702c02 + .word 0xcb802c02 + .word 0xcb902c02 + .word 0xcba02c02 + .word 0xcbb02c02 + .word 0xcbc02c02 + .word 0xcbd02c02 + .word 0xcbe02c02 + .word 0xcbf02c02 + .word 0xcc002c02 + .word 0xcc102c02 + .word 0xcc202c02 + .word 0xcc302c02 + .word 0xcc402c02 + .word 0xcc502c02 + .word 0xcc602c02 + .word 0xcc702c02 + .word 0xcc802c02 + .word 0xcc902c02 + .word 0xcca02c02 + .word 0xccb02c02 + .word 0xccc02c02 + .word 0xccd02c02 + .word 0xcce02c02 + .word 0xccf02c02 + .word 0xcd002c02 + .word 0xcd102c02 + .word 0xcd202c02 + .word 0xcd302c02 + .word 0xcd402c02 + .word 0xcd502c02 + .word 0xcd602c02 + .word 0xcd702c02 + .word 0xcd802c02 + .word 0xcd902c02 + .word 0xcda02c02 + .word 0xcdb02c02 + .word 0xcdc02c02 + .word 0xcdd02c02 + .word 0xcde02c02 + .word 0xcdf02c02 + .word 0xce002c02 + .word 0xce102c02 + .word 0xce202c02 + .word 0xce302c02 + .word 0xce402c02 + .word 0xce502c02 + .word 0xce602c02 + .word 0xce702c02 + .word 0xce802c02 + .word 0xce902c02 + .word 0xcea02c02 + .word 0xceb02c02 + .word 0xcec02c02 + .word 0xced02c02 + .word 0xcee02c02 + .word 0xcef02c02 + .word 0xcf002c02 + .word 0xcf102c02 + .word 0xcf202c02 + .word 0xcf302c02 + .word 0xcf402c02 + .word 0xcf502c02 + .word 0xcf602c02 + .word 0xcf702c02 + .word 0xcf802c02 + .word 0xcf902c02 + .word 0xcfa02c02 + .word 0xcfb02c02 + .word 0xcfc02c02 + .word 0xcfd02c02 + .word 0xcfe02c02 + .word 0xcff02c02 + .word 0xd0002c02 + .word 0xd0102c02 + .word 0xd0202c02 + .word 0xd0302c02 + .word 0xd0402c02 + .word 0xd0502c02 + .word 0xd0602c02 + .word 0xd0702c02 + .word 0xd0802c02 + .word 0xd0902c02 + .word 0xd0a02c02 + .word 0xd0b02c02 + .word 0xd0c02c02 + .word 0xd0d02c02 + .word 0xd0e02c02 + .word 0xd0f02c02 + .word 0xd1002c02 + .word 0xd1102c02 + .word 0xd1202c02 + .word 0xd1302c02 + .word 0xd1402c02 + .word 0xd1502c02 + .word 0xd1602c02 + .word 0xd1702c02 + .word 0xd1802c02 + .word 0xd1902c02 + .word 0xd1a02c02 + .word 0xd1b02c02 + .word 0xd1c02c02 + .word 0xd1d02c02 + .word 0xd1e02c02 + .word 0xd1f02c02 + .word 0xd2002c02 + .word 0xd2102c02 + .word 0xd2202c02 + .word 0xd2302c02 + .word 0xd2402c02 + .word 0xd2502c02 + .word 0xd2602c02 + .word 0xd2702c02 + .word 0xd2802c02 + .word 0xd2902c02 + .word 0xd2a02c02 + .word 0xd2b02c02 + .word 0xd2c02c02 + .word 0xd2d02c02 + .word 0xd2e02c02 + .word 0xd2f02c02 + .word 0xd3002c02 + .word 0xd3102c02 + .word 0xd3202c02 + .word 0xd3302c02 + .word 0xd3402c02 + .word 0xd3502c02 + .word 0xd3602c02 + .word 0xd3702c02 + .word 0xd3802c02 + .word 0xd3902c02 + .word 0xd3a02c02 + .word 0xd3b02c02 + .word 0xd3c02c02 + .word 0xd3d02c02 + .word 0xd3e02c02 + .word 0xd3f02c02 + .word 0xd4002c02 + .word 0xd4102c02 + .word 0xd4202c02 + .word 0xd4302c02 + .word 0xd4402c02 + .word 0xd4502c02 + .word 0xd4602c02 + .word 0xd4702c02 + .word 0xd4802c02 + .word 0xd4902c02 + .word 0xd4a02c02 + .word 0xd4b02c02 + .word 0xd4c02c02 + .word 0xd4d02c02 + .word 0xd4e02c02 + .word 0xd4f02c02 + .word 0xd5002c02 + .word 0xd5102c02 + .word 0xd5202c02 + .word 0xd5302c02 + .word 0xd5402c02 + .word 0xd5502c02 + .word 0xd5602c02 + .word 0xd5702c02 + .word 0xd5802c02 + .word 0xd5902c02 + .word 0xd5a02c02 + .word 0xd5b02c02 + .word 0xd5c02c02 + .word 0xd5d02c02 + .word 0xd5e02c02 + .word 0xd5f02c02 + .word 0xd6002c02 + .word 0xd6102c02 + .word 0xd6202c02 + .word 0xd6302c02 + .word 0xd6402c02 + .word 0xd6502c02 + .word 0xd6602c02 + .word 0xd6702c02 + .word 0xd6802c02 + .word 0xd6902c02 + .word 0xd6a02c02 + .word 0xd6b02c02 + .word 0xd6c02c02 + .word 0xd6d02c02 + .word 0xd6e02c02 + .word 0xd6f02c02 + .word 0xd7002c02 + .word 0xd7102c02 + .word 0xd7202c02 + .word 0xd7302c02 + .word 0xd7402c02 + .word 0xd7502c02 + .word 0xd7602c02 + .word 0xd7702c02 + .word 0xd7802c02 + .word 0xd7902c02 + .word 0xd7a02c02 + .word 0xd7b02c02 + .word 0xd7c02c02 + .word 0xd7d02c02 + .word 0xd7e02c02 + .word 0xd7f02c02 + .word 0xd8002c02 + .word 0xd8102c02 + .word 0xd8202c02 + .word 0xd8302c02 + .word 0xd8402c02 + .word 0xd8502c02 + .word 0xd8602c02 + .word 0xd8702c02 + .word 0xd8802c02 + .word 0xd8902c02 + .word 0xd8a02c02 + .word 0xd8b02c02 + .word 0xd8c02c02 + .word 0xd8d02c02 + .word 0xd8e02c02 + .word 0xd8f02c02 + .word 0xd9002c02 + .word 0xd9102c02 + .word 0xd9202c02 + .word 0xd9302c02 + .word 0xd9402c02 + .word 0xd9502c02 + .word 0xd9602c02 + .word 0xd9702c02 + .word 0xd9802c02 + .word 0xd9902c02 + .word 0xd9a02c02 + .word 0xd9b02c02 + .word 0xd9c02c02 + .word 0xd9d02c02 + .word 0xd9e02c02 + .word 0xd9f02c02 + .word 0xda002c02 + .word 0xda102c02 + .word 0xda202c02 + .word 0xda302c02 + .word 0xda402c02 + .word 0xda502c02 + .word 0xda602c02 + .word 0xda702c02 + .word 0xda802c02 + .word 0xda902c02 + .word 0xdaa02c02 + .word 0xdab02c02 + .word 0xdac02c02 + .word 0xdad02c02 + .word 0xdae02c02 + .word 0xdaf02c02 + .word 0xdb002c02 + .word 0xdb102c02 + .word 0xdb202c02 + .word 0xdb302c02 + .word 0xdb402c02 + .word 0xdb502c02 + .word 0xdb602c02 + .word 0xdb702c02 + .word 0xdb802c02 + .word 0xdb902c02 + .word 0xdba02c02 + .word 0xdbb02c02 + .word 0xdbc02c02 + .word 0xdbd02c02 + .word 0xdbe02c02 + .word 0xdbf02c02 + .word 0xdc002c02 + .word 0xdc102c02 + .word 0xdc202c02 + .word 0xdc302c02 + .word 0xdc402c02 + .word 0xdc502c02 + .word 0xdc602c02 + .word 0xdc702c02 + .word 0xdc802c02 + .word 0xdc902c02 + .word 0xdca02c02 + .word 0xdcb02c02 + .word 0xdcc02c02 + .word 0xdcd02c02 + .word 0xdce02c02 + .word 0xdcf02c02 + .word 0xdd002c02 + .word 0xdd102c02 + .word 0xdd202c02 + .word 0xdd302c02 + .word 0xdd402c02 + .word 0xdd502c02 + .word 0xdd602c02 + .word 0xdd702c02 + .word 0xdd802c02 + .word 0xdd902c02 + .word 0xdda02c02 + .word 0xddb02c02 + .word 0xddc02c02 + .word 0xddd02c02 + .word 0xdde02c02 + .word 0xddf02c02 + .word 0xde002c02 + .word 0xde102c02 + .word 0xde202c02 + .word 0xde302c02 + .word 0xde402c02 + .word 0xde502c02 + .word 0xde602c02 + .word 0xde702c02 + .word 0xde802c02 + .word 0xde902c02 + .word 0xdea02c02 + .word 0xdeb02c02 + .word 0xdec02c02 + .word 0xded02c02 + .word 0xdee02c02 + .word 0xdef02c02 + .word 0xdf002c02 + .word 0xdf102c02 + .word 0xdf202c02 + .word 0xdf302c02 + .word 0xdf402c02 + .word 0xdf502c02 + .word 0xdf602c02 + .word 0xdf702c02 + .word 0xdf802c02 + .word 0xdf902c02 + .word 0xdfa02c02 + .word 0xdfb02c02 + .word 0xdfc02c02 + .word 0xdfd02c02 + .word 0xdfe02c02 + .word 0xdff02c02 + .word 0xe0002c02 + .word 0xe0102c02 + .word 0xe0202c02 + .word 0xe0302c02 + .word 0xe0402c02 + .word 0xe0502c02 + .word 0xe0602c02 + .word 0xe0702c02 + .word 0xe0802c02 + .word 0xe0902c02 + .word 0xe0a02c02 + .word 0xe0b02c02 + .word 0xe0c02c02 + .word 0xe0d02c02 + .word 0xe0e02c02 + .word 0xe0f02c02 + .word 0xe1002c02 + .word 0xe1102c02 + .word 0xe1202c02 + .word 0xe1302c02 + .word 0xe1402c02 + .word 0xe1502c02 + .word 0xe1602c02 + .word 0xe1702c02 + .word 0xe1802c02 + .word 0xe1902c02 + .word 0xe1a02c02 + .word 0xe1b02c02 + .word 0xe1c02c02 + .word 0xe1d02c02 + .word 0xe1e02c02 + .word 0xe1f02c02 + .word 0xe2002c02 + .word 0xe2102c02 + .word 0xe2202c02 + .word 0xe2302c02 + .word 0xe2402c02 + .word 0xe2502c02 + .word 0xe2602c02 + .word 0xe2702c02 + .word 0xe2802c02 + .word 0xe2902c02 + .word 0xe2a02c02 + .word 0xe2b02c02 + .word 0xe2c02c02 + .word 0xe2d02c02 + .word 0xe2e02c02 + .word 0xe2f02c02 + .word 0xe3002c02 + .word 0xe3102c02 + .word 0xe3202c02 + .word 0xe3302c02 + .word 0xe3402c02 + .word 0xe3502c02 + .word 0xe3602c02 + .word 0xe3702c02 + .word 0xe3802c02 + .word 0xe3902c02 + .word 0xe3a02c02 + .word 0xe3b02c02 + .word 0xe3c02c02 + .word 0xe3d02c02 + .word 0xe3e02c02 + .word 0xe3f02c02 + .word 0xe4002c02 + .word 0xe4102c02 + .word 0xe4202c02 + .word 0xe4302c02 + .word 0xe4402c02 + .word 0xe4502c02 + .word 0xe4602c02 + .word 0xe4702c02 + .word 0xe4802c02 + .word 0xe4902c02 + .word 0xe4a02c02 + .word 0xe4b02c02 + .word 0xe4c02c02 + .word 0xe4d02c02 + .word 0xe4e02c02 + .word 0xe4f02c02 + .word 0xe5002c02 + .word 0xe5102c02 + .word 0xe5202c02 + .word 0xe5302c02 + .word 0xe5402c02 + .word 0xe5502c02 + .word 0xe5602c02 + .word 0xe5702c02 + .word 0xe5802c02 + .word 0xe5902c02 + .word 0xe5a02c02 + .word 0xe5b02c02 + .word 0xe5c02c02 + .word 0xe5d02c02 + .word 0xe5e02c02 + .word 0xe5f02c02 + .word 0xe6002c02 + .word 0xe6102c02 + .word 0xe6202c02 + .word 0xe6302c02 + .word 0xe6402c02 + .word 0xe6502c02 + .word 0xe6602c02 + .word 0xe6702c02 + .word 0xe6802c02 + .word 0xe6902c02 + .word 0xe6a02c02 + .word 0xe6b02c02 + .word 0xe6c02c02 + .word 0xe6d02c02 + .word 0xe6e02c02 + .word 0xe6f02c02 + .word 0xe7002c02 + .word 0xe7102c02 + .word 0xe7202c02 + .word 0xe7302c02 + .word 0xe7402c02 + .word 0xe7502c02 + .word 0xe7602c02 + .word 0xe7702c02 + .word 0xe7802c02 + .word 0xe7902c02 + .word 0xe7a02c02 + .word 0xe7b02c02 + .word 0xe7c02c02 + .word 0xe7d02c02 + .word 0xe7e02c02 + .word 0xe7f02c02 + .word 0xe8002c02 + .word 0xe8102c02 + .word 0xe8202c02 + .word 0xe8302c02 + .word 0xe8402c02 + .word 0xe8502c02 + .word 0xe8602c02 + .word 0xe8702c02 + .word 0xe8802c02 + .word 0xe8902c02 + .word 0xe8a02c02 + .word 0xe8b02c02 + .word 0xe8c02c02 + .word 0xe8d02c02 + .word 0xe8e02c02 + .word 0xe8f02c02 + .word 0xe9002c02 + .word 0xe9102c02 + .word 0xe9202c02 + .word 0xe9302c02 + .word 0xe9402c02 + .word 0xe9502c02 + .word 0xe9602c02 + .word 0xe9702c02 + .word 0xe9802c02 + .word 0xe9902c02 + .word 0xe9a02c02 + .word 0xe9b02c02 + .word 0xe9c02c02 + .word 0xe9d02c02 + .word 0xe9e02c02 + .word 0xe9f02c02 + .word 0xea002c02 + .word 0xea102c02 + .word 0xea202c02 + .word 0xea302c02 + .word 0xea402c02 + .word 0xea502c02 + .word 0xea602c02 + .word 0xea702c02 + .word 0xea802c02 + .word 0xea902c02 + .word 0xeaa02c02 + .word 0xeab02c02 + .word 0xeac02c02 + .word 0xead02c02 + .word 0xeae02c02 + .word 0xeaf02c02 + .word 0xeb002c02 + .word 0xeb102c02 + .word 0xeb202c02 + .word 0xeb302c02 + .word 0xeb402c02 + .word 0xeb502c02 + .word 0xeb602c02 + .word 0xeb702c02 + .word 0xeb802c02 + .word 0xeb902c02 + .word 0xeba02c02 + .word 0xebb02c02 + .word 0xebc02c02 + .word 0xebd02c02 + .word 0xebe02c02 + .word 0xebf02c02 + .word 0xec002c02 + .word 0xec102c02 + .word 0xec202c02 + .word 0xec302c02 + .word 0xec402c02 + .word 0xec502c02 + .word 0xec602c02 + .word 0xec702c02 + .word 0xec802c02 + .word 0xec902c02 + .word 0xeca02c02 + .word 0xecb02c02 + .word 0xecc02c02 + .word 0xecd02c02 + .word 0xece02c02 + .word 0xecf02c02 + .word 0xed002c02 + .word 0xed102c02 + .word 0xed202c02 + .word 0xed302c02 + .word 0xed402c02 + .word 0xed502c02 + .word 0xed602c02 + .word 0xed702c02 + .word 0xed802c02 + .word 0xed902c02 + .word 0xeda02c02 + .word 0xedb02c02 + .word 0xedc02c02 + .word 0xedd02c02 + .word 0xede02c02 + .word 0xedf02c02 + .word 0xee002c02 + .word 0xee102c02 + .word 0xee202c02 + .word 0xee302c02 + .word 0xee402c02 + .word 0xee502c02 + .word 0xee602c02 + .word 0xee702c02 + .word 0xee802c02 + .word 0xee902c02 + .word 0xeea02c02 + .word 0xeeb02c02 + .word 0xeec02c02 + .word 0xeed02c02 + .word 0xeee02c02 + .word 0xeef02c02 + .word 0xef002c02 + .word 0xef102c02 + .word 0xef202c02 + .word 0xef302c02 + .word 0xef402c02 + .word 0xef502c02 + .word 0xef602c02 + .word 0xef702c02 + .word 0xef802c02 + .word 0xef902c02 + .word 0xefa02c02 + .word 0xefb02c02 + .word 0xefc02c02 + .word 0xefd02c02 + .word 0xefe02c02 + .word 0xeff02c02 + .word 0xf0002c02 + .word 0xf0102c02 + .word 0xf0202c02 + .word 0xf0302c02 + .word 0xf0402c02 + .word 0xf0502c02 + .word 0xf0602c02 + .word 0xf0702c02 + .word 0xf0802c02 + .word 0xf0902c02 + .word 0xf0a02c02 + .word 0xf0b02c02 + .word 0xf0c02c02 + .word 0xf0d02c02 + .word 0xf0e02c02 + .word 0xf0f02c02 + .word 0xf1002c02 + .word 0xf1102c02 + .word 0xf1202c02 + .word 0xf1302c02 + .word 0xf1402c02 + .word 0xf1502c02 + .word 0xf1602c02 + .word 0xf1702c02 + .word 0xf1802c02 + .word 0xf1902c02 + .word 0xf1a02c02 + .word 0xf1b02c02 + .word 0xf1c02c02 + .word 0xf1d02c02 + .word 0xf1e02c02 + .word 0xf1f02c02 + .word 0xf2002c02 + .word 0xf2102c02 + .word 0xf2202c02 + .word 0xf2302c02 + .word 0xf2402c02 + .word 0xf2502c02 + .word 0xf2602c02 + .word 0xf2702c02 + .word 0xf2802c02 + .word 0xf2902c02 + .word 0xf2a02c02 + .word 0xf2b02c02 + .word 0xf2c02c02 + .word 0xf2d02c02 + .word 0xf2e02c02 + .word 0xf2f02c02 + .word 0xf3002c02 + .word 0xf3102c02 + .word 0xf3202c02 + .word 0xf3302c02 + .word 0xf3402c02 + .word 0xf3502c02 + .word 0xf3602c02 + .word 0xf3702c02 + .word 0xf3802c02 + .word 0xf3902c02 + .word 0xf3a02c02 + .word 0xf3b02c02 + .word 0xf3c02c02 + .word 0xf3d02c02 + .word 0xf3e02c02 + .word 0xf3f02c02 + .word 0xf4002c02 + .word 0xf4102c02 + .word 0xf4202c02 + .word 0xf4302c02 + .word 0xf4402c02 + .word 0xf4502c02 + .word 0xf4602c02 + .word 0xf4702c02 + .word 0xf4802c02 + .word 0xf4902c02 + .word 0xf4a02c02 + .word 0xf4b02c02 + .word 0xf4c02c02 + .word 0xf4d02c02 + .word 0xf4e02c02 + .word 0xf4f02c02 + .word 0xf5002c02 + .word 0xf5102c02 + .word 0xf5202c02 + .word 0xf5302c02 + .word 0xf5402c02 + .word 0xf5502c02 + .word 0xf5602c02 + .word 0xf5702c02 + .word 0xf5802c02 + .word 0xf5902c02 + .word 0xf5a02c02 + .word 0xf5b02c02 + .word 0xf5c02c02 + .word 0xf5d02c02 + .word 0xf5e02c02 + .word 0xf5f02c02 + .word 0xf6002c02 + .word 0xf6102c02 + .word 0xf6202c02 + .word 0xf6302c02 + .word 0xf6402c02 + .word 0xf6502c02 + .word 0xf6602c02 + .word 0xf6702c02 + .word 0xf6802c02 + .word 0xf6902c02 + .word 0xf6a02c02 + .word 0xf6b02c02 + .word 0xf6c02c02 + .word 0xf6d02c02 + .word 0xf6e02c02 + .word 0xf6f02c02 + .word 0xf7002c02 + .word 0xf7102c02 + .word 0xf7202c02 + .word 0xf7302c02 + .word 0xf7402c02 + .word 0xf7502c02 + .word 0xf7602c02 + .word 0xf7702c02 + .word 0xf7802c02 + .word 0xf7902c02 + .word 0xf7a02c02 + .word 0xf7b02c02 + .word 0xf7c02c02 + .word 0xf7d02c02 + .word 0xf7e02c02 + .word 0xf7f02c02 + .word 0xf8002c02 + .word 0xf8102c02 + .word 0xf8202c02 + .word 0xf8302c02 + .word 0xf8402c02 + .word 0xf8502c02 + .word 0xf8602c02 + .word 0xf8702c02 + .word 0xf8802c02 + .word 0xf8902c02 + .word 0xf8a02c02 + .word 0xf8b02c02 + .word 0xf8c02c02 + .word 0xf8d02c02 + .word 0xf8e02c02 + .word 0xf8f02c02 + .word 0xf9002c02 + .word 0xf9102c02 + .word 0xf9202c02 + .word 0xf9302c02 + .word 0xf9402c02 + .word 0xf9502c02 + .word 0xf9602c02 + .word 0xf9702c02 + .word 0xf9802c02 + .word 0xf9902c02 + .word 0xf9a02c02 + .word 0xf9b02c02 + .word 0xf9c02c02 + .word 0xf9d02c02 + .word 0xf9e02c02 + .word 0xf9f02c02 + .word 0xfa002c02 + .word 0xfa102c02 + .word 0xfa202c02 + .word 0xfa302c02 + .word 0xfa402c02 + .word 0xfa502c02 + .word 0xfa602c02 + .word 0xfa702c02 + .word 0xfa802c02 + .word 0xfa902c02 + .word 0xfaa02c02 + .word 0xfab02c02 + .word 0xfac02c02 + .word 0xfad02c02 + .word 0xfae02c02 + .word 0xfaf02c02 + .word 0xfb002c02 + .word 0xfb102c02 + .word 0xfb202c02 + .word 0xfb302c02 + .word 0xfb402c02 + .word 0xfb502c02 + .word 0xfb602c02 + .word 0xfb702c02 + .word 0xfb802c02 + .word 0xfb902c02 + .word 0xfba02c02 + .word 0xfbb02c02 + .word 0xfbc02c02 + .word 0xfbd02c02 + .word 0xfbe02c02 + .word 0xfbf02c02 + .word 0xfc002c02 + .word 0xfc102c02 + .word 0xfc202c02 + .word 0xfc302c02 + .word 0xfc402c02 + .word 0xfc502c02 + .word 0xfc602c02 + .word 0xfc702c02 + .word 0xfc802c02 + .word 0xfc902c02 + .word 0xfca02c02 + .word 0xfcb02c02 + .word 0xfcc02c02 + .word 0xfcd02c02 + .word 0xfce02c02 + .word 0xfcf02c02 + .word 0xfd002c02 + .word 0xfd102c02 + .word 0xfd202c02 + .word 0xfd302c02 + .word 0xfd402c02 + .word 0xfd502c02 + .word 0xfd602c02 + .word 0xfd702c02 + .word 0xfd802c02 + .word 0xfd902c02 + .word 0xfda02c02 + .word 0xfdb02c02 + .word 0xfdc02c02 + .word 0xfdd02c02 + .word 0xfde02c02 + .word 0xfdf02c02 + .word 0xfe002c02 + .word 0xfe102c02 + .word 0xfe202c02 + .word 0xfe302c02 + .word 0xfe402c02 + .word 0xfe502c02 + .word 0xfe602c02 + .word 0xfe702c02 + .word 0xfe802c02 + .word 0xfe902c02 + .word 0xfea02c02 + .word 0xfeb02c02 + .word 0xfec02c02 + .word 0xfed02c02 + .word 0xfee02c02 + .word 0xfef02c02 + .word 0xff002c02 + .word 0xff102c02 + .word 0xff202c02 + .word 0xff302c02 + .word 0xff402c02 + .word 0xff502c02 + .word 0xff602c02 + .word 0xff702c02 + .word 0xff802c02 + .word 0xff902c02 + .word 0xffa02c02 + .word 0xffb02c02 + .word 0xffc02c02 + .word 0xffd02c02 + .word 0xffe02c02 + .word 0xfff02c02 +#endif /* CFG_SHMOO */ + +/* Entry point */ + .section .text.startup + + .globl startup +startup: + b tr_rst /* 0 - reset */ + ldr pc,_tr_und /* 4 - undefined instruction */ + ldr pc,_tr_swi /* 8 - software interrupt */ + ldr pc,_tr_iab /* 0xc - prefetch abort */ + ldr pc,_tr_dab /* 0x10 - data abort */ + ldr pc,_tr_bad /* 0x14 - reserved */ + ldr pc,_tr_irq /* 0x18 - external interrupt */ + ldr pc,_tr_fiq /* 0x1c - fast interrupt */ + +_tr_und: + .word tr_und +_tr_swi: + .word tr_swi +_tr_iab: + .word tr_iab +_tr_dab: + .word tr_dab +_tr_bad: + .word tr_bad +_tr_irq: + .word tr_irq +_tr_fiq: + .word tr_fiq +_pad: + .word 0x12345678 /* now 16*4=64 */ + + .org (BISZ_OFFSET-4) +_ddrclk: + .word 0x0 + /* Record the size of the binary */ + .org BISZ_OFFSET + + .word BISZ_MAGIC + .word text_start + .word text_end + .word data_start + .word data_end + .word bss_start + .word bss_end + .word _end + + .balign envram_ofs + /* Embedded NVRAM */ + .global embedded_nvram +embedded_nvram: + .fill 0x400,4,~0x48534C46 /* 'FLSH' */ + .long 0x4c5a4d41 /* LZMA NVRAM Supported */ + +#ifdef _CFE_ +#if CFG_EMBEDDED_PIC +#define RUNTIME_RELOC_START __runtime_reloc_start +#define RUNTIME_RELOC_STOP __runtime_reloc_stop +#else +#define RUNTIME_RELOC_START 0 +#define RUNTIME_RELOC_STOP 0 +#endif + +#include "segtable.h" + + .globl segment_table +segment_table: + .word text_end /* [ 0] End of text (R_SEG_ETEXT) */ + .word data_start /* [ 1] Beginning of data (R_SEG_FDATA) */ + .word data_end /* [ 2] End of data (R_SEG_EDATA) */ + .word _end /* [ 3] End of BSS (R_SEG_END) */ + .word text_start /* [ 4] Beginning of text (R_SEG_FTEXT) */ + .word bss_start /* [ 5] Beginning of BSS (R_SEG_FBSS) */ + .word 0 /* [ 6] Global Pointer (R_SEG_GP) */ + .word RUNTIME_RELOC_START /* [ 7] Beginning of reloc entries */ + .word RUNTIME_RELOC_STOP /* [ 8] End of reloc entries */ + .word 0 /* [ 9] R_SEG_APIENTRY */ +#endif /* __CFE_ */ + +/************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + *************************************************************************/ + +/* + * the actual reset code + */ +tr_rst: + mrs r0,cpsr + mov r1,#(PS_MM) + bic r0,r0,r1 + /* Switch to system mode and make sure interrupts are disabled */ + mov r1,#(PS_I | PS_F | PS_SYS) + orr r0,r0,r1 + msr cpsr,r0 +initcpu: + mov r0,#0 + + /* Initialize cp15 registers */ + mcr p15,0,r0,c5,c0,0 /* DFSR */ + mcr p15,0,r0,c5,c0,1 /* IFSR */ + mcr p15,0,r0,c6,c0,0 /* DFAR */ + + /* Initialize system control register */ + mrc p15,0,r1,c1,c0,0 + bic r1,r1,#0x7 /* Clear C, A, M bits */ + bic r1,r1,#(0x1 << 12) /* Clear I bit */ + orr r1,r1,#0x2000 /* Set V bit: high vectors (0xffff0000) */ + orr r1,r1,#0x2 /* Set A bit: enable strict alignment */ + mcr p15,0,r1,c1,c0,0 + + mcr p15,0,r0,c8,c7,0 /* Invalidate TLB */ + mcr p15,0,r0,c7,c5,0 /* Invalidate icache */ + mcr p15,0,r0,c7,c5,6 /* Invalidate BTAC */ + mcr p15,0,r0,c7,c10,4 /* DSB */ + mcr p15,0,r0,c7,c5,4 /* ISB */ + + /* Identify CPU ID */ + mrc p15,0,r9,c0,c0,0 /* retrieve cpu part no */ + ldr r8,=CORTEX_ID_MASK + and r9,r9,r8 + ldr r8,=CORTEX_ID_A7 + cmp r9,r8 + beq check_startaddr + + /* Cortex-A9. Identify current core*/ + mrc p15,0,r0,c0,c0,5 + and r0,r0,#0xf /* retrieve cpu core id */ + cmp r0,#0 /* cpu core 0? */ + beq check_startaddr + + /* Changed the jump address for core 1 */ + ldr r0,=0xffff002c /* This address contains a wfe instruction */ + ldr r1,=0xffff0000 /* SKU ROM starting address */ + str r0, [r1, #0x400] + + ldr pc,=0xffff002c /* Go back to SKU ROM, waiting kernel SMP */ + +check_startaddr: + adrl r0,startup /* r0: source start address */ + ldr r1,=startup /* r1: target address */ + cmp r0,r1 + beq szmem + + cmp r9,r8 /* Cortex-A7? */ + beq enable_smp + + /* Cortex-A9, Wake up core 1 */ + mov r0,#0 + mcr p15,0,r0,c7,c10,4 + sev + b enable_cache + +enable_smp: + /* Enable SMP before cache enabled, for Cortex-A7 series core */ + mrc p15,0,r1,c1,c0,1 + orr r1,r1,#0x40 + mcr p15,0,r1,c1,c0,1 + +enable_cache: + /* Enable I cache */ + mrc p15,0,r1,c1,c0,0 + orr r1,r1,#0x1800 /* Enable I$ and branch prediction */ + mcr p15,0,r1,c1,c0,0 + +#if defined(_CFEZ_) +genpll_mdiv: + /* Correct the GENPLL setting for OTPed 4709C0 */ + ldr r0, =0x18000000 /* SI_ENUM_BASE_DEFAULT */ + ldr r1, =0 /* CC_CHIPID */ + ldr r1, [r0, r1] + ldr r0, =0x0000ffff /* CID_ID_MASK */ + and r2, r1, r0 + ldr r0, =53030 /* BCM4709C0_CHIP_ID */ + cmp r2, r0 /* r2 to store chip id */ + bne genpll_mdiv_done + ldr r0, =0x00300000 /* CID_PACKAGE_OPTION_MASK */ + and r2, r1, r0 + cmp r2, #0 /* BCM4709C0 package is 0 */ + bne genpll_mdiv_done + + /* To set correct CH0-5 mdiv */ + ldr r0,=0x1800c154 + ldr r0,[r0] + ldr r1,=0x3ff00000 /* Get CRU_GENPLL_CONTROL5 bit[29:20] */ + and r0,r0,r1 + ldr r1,=0x05000000 /* Check GENPLL NDIV = 0x50? */ + cmp r0,r1 + bne genpll_mdiv_done /* Not equal. Skip this */ + /* If we have done it, skip it */ + ldr r0,=0x1800c15c /* CRU_GENPLL_CONTROL7 */ + ldr r0,[r0] + ldr r1,=0x00ff0000 + and r0,r0,r1 /* Get CH3_MDIV */ + ldr r1,=0x00040000 /* If CH3_MDIV = 4, done */ + cmp r0,r1 + beq genpll_mdiv_done + /* Configure mdiv for GENPLL channel 0~3 */ + /* Set CRU_CLKSET_KEY to unlock */ + ldr r0,=0x1800c180 + ldr r1,=0x0000ea68 + str r1,[r0] + /* Configure CRU_GENPLL_CONTROL6 */ + ldr r0,=0x1800c158 + ldr r1,[r0] + ldr r2,=0xff000000 + and r1,r1,r2 + ldr r2,=0x00080c32 /* CH0_MDIV = 8, CH1_MDIV = 12, CH2_MDIV = 50 */ + orr r1,r1,r2 + str r1,[r0] + /* Configure CRU_GENPLL_CONTROL7 */ + ldr r0,=0x1800c15c + ldr r1,[r0] + ldr r2,=0xff000000 + and r1,r1,r2 + ldr r2,=0x00040810 /* CH3_MDIV = 4, CH4_MDIV = 8, CH5_MDIV = 16 */ + orr r1,r1,r2 + str r1,[r0] + /* Configure CRU_GENPLL_CONTROL5 */ + ldr r0,=0x1800c154 + ldr r1,[r0] + ldr r2,=0x80000000 + orr r1,r1,r2 /* Enable SEL_SW_SETTING */ + str r1,[r0] + /* Configure CRU_GENPLL_CONTROL1 */ + ldr r0,=0x1800c144 + ldr r1,[r0] + bic r1,r1,#0xf /* Reload mdiv for CH0~3 */ + str r1,[r0] + orr r1,r1,#0xf + str r1,[r0] + bic r1,r1,#0xf + str r1,[r0] + /* Set CRU_CLKSET_KEY to unlock */ + ldr r0,=0x1800c180 + ldr r1,=0x0 + str r1,[r0] +genpll_mdiv_done: +#endif /* _CFEZ_ */ + +#ifdef CFG_SHMOO + cmp r9,r8 /* Cortex-A7? */ + beq ca7_shmoo_init + + /* Cortex-A9, start l1/l2 mmu init for SHMOO */ +ca9_shmoo_init: + /* Invalidate data cache */ + bl cpu_inv_dcache_all + + /* Enable D cache */ + mcr p15,0,r0,c7,c10,4 /* DSB */ + mrc p15,0,r1,c1,c0,0 + orr r1,r1,#0x4 + mcr p15,0,r1,c1,c0,0 + mcr p15,0,r0,c7,c5,4 /* ISB */ + + /* Invalidate TLB */ + mcr p15,0,r0,c8,c7,0 + +scu_enable: + ldr r1,=IHOST_SCU_INVALIDATE + mov r2,#0xff + str r2,[r1] + ldr r1,=IHOST_SCU_CONTROL + ldr r2,[r1] + orr r2,r2,#0x1 + str r2,[r1] +mmu_init: + ldr r1,=startup + ldr r2,=page_table + sub r2,r2,r1 + adrl r1,startup + add r1,r1,r2 + + /* Configure translation table base (TTB) control register cp15,c2 + * to a value of all zeros, indicates we are using TTB register 0 + */ + mov r0,#0 + mcr p15,0,r0,c2,c0,2 + /* Load page table address to cp15 */ + mcr p15,0,r1,c2,c0,0 + /* Set the access control to client */ + ldr r1,=0xffffffff + mcr p15,0,r1,c3,c0,0 + /* Enable MMU */ + mrc p15,0,r1,c1,c0,0 + orr r1,r1,#0x1 + mcr p15,0,r1,c1,c0,0 + mcr p15,0,r0,c7,c5,4 /* ISB */ + +l2cc_init: + ldr r1,=SI_ENUM_BASE_DEFAULT + ldr r2,=CC_CHIPID + ldr r2,[r1,r2] + ldr r1,=CID_ID_MASK + and r2,r2,r1 + ldr r1,=0xcf12 /* NS Ax/Bx */ + cmp r2,r1 + beq l2cc_256k + ldr r1,=0xcf26 /* NS 47094 */ + cmp r2,r1 + beq l2cc_256k + ldr r1,=0xcf19 + cmp r2,r1 + bge l2cc_512k +l2cc_256k: + ldr r1,=0x0a130000 + ldr r4,=0x111 + b l2cc_inv +l2cc_512k: + ldr r1,=0x0a150000 + ldr r4,=0x131 +l2cc_inv: + ldr r2,=IHOST_L2C_CACHE_ID + ldr r3,[r2,#0x104] + bic r3,r3,#0x000f0000 + orr r3,r3,r1 + str r3,[r2,#0x104] + ldr r1,=0x0 + str r1,[r2,#0x108] + str r4,[r2,#0x10c] + ldr r1,=0xffff + str r1,[r2,#0x77c] +test_inv_way: + ldr r1,[r2,#0x77c] + cmp r1,r0 + bne test_inv_way + + ldr r1,=0x1ff + str r1,[r2,#0x220] /* int_clear */ + mov r1,#0x1 + str r1,[r2,#0x100] /* control */ + mcr p15,0,r0,c7,c10,4 /* DSB */ + mcr p15,0,r0,c7,c5,4 /* ISB */ + +l2cc_lockdown: + ldr r1,=0xc0000000 + ldr r2,=0xc0040000 /* 256KB */ + ldr r4,=0xa5a5a5a5 + ldr r5,=0xa5a5a5a5 + ldr r6,=0xa5a5a5a5 + ldr r7,=0xa5a5a5a5 + ldr r8,=0xa5a5a5a5 + ldr r9,=0xa5a5a5a5 + ldr r10,=0xa5a5a5a5 + ldr r11,=0xa5a5a5a5 + /* Enable lockdown by line */ + mov r3,#0x01 + ldr r0,=IHOST_L2C_CACHE_ID + str r3,[r0,#0x950] +1: + stmia r1!,{r4-r11} + ldr r3,=0x10 +cdelay1: + sub r3,r3,#1 + cmp r3,#0 + bne cdelay1 + cmp r1,r2 + bne 1b + + /* Disable lockdown by line */ + mov r3,#0 + ldr r0,=IHOST_L2C_CACHE_ID + str r3,[r0,#0x950] +l2cc_init_done: + b shmoo_init_done +ca7_shmoo_init: + /* Need to add shmoo init code for ca7 */ +shmoo_init_done: +#endif /* CFG_SHMOO */ + /* Identify CPU ID */ + mrc p15,0,r7,c0,c0,0 /* retrieve cpu part no */ + ldr r6,=CORTEX_ID_MASK + and r7,r7,r6 + ldr r6,=CORTEX_ID_A7 + cmp r7,r6 + beq init_pcie + + /* BCM4708 WAR for PCIE2 */ + ldr r0,=0x1a000000 + ldr r1,=0x0 + str r1,[r0] + ldr r0,=0x18130e04 + ldr r1,=0x0 + str r1,[r0] + ldr r0,=0x18130e00 + ldr r1,=0x1 + str r1,[r0] + +init_pcie: + ldr r0,=SI_ENUM_BASE_DEFAULT /* r0: core regs SI base address */ + ldr r1,=CC_EROMPTR + ldr r1,[r0,r1] /* r1: erom pointer */ +1: ldr r2,[r1] /* r2: erom entry */ + ldr r3,=(ER_TAG | ER_VALID) + and r3,r3,r2 + cmp r3,#(ER_END | ER_VALID) /* Is this the END marker? */ + beq no_pcie /* Yes: done and did not find pcie */ + + cmp r3,#(ER_CI | ER_VALID) + beq 2f + + add r1,r1,#4 /* Next erom entry */ + b 1b + +no_pcie: + b find_bootdev + + /* Found a CIA */ +2: add r1,r1,#8 /* Skip both CIA & CIB */ + ldr r3,=CIA_CID_MASK + and r3,r3,r2 + ldr r4,=(NS_PCIEG2_CORE_ID << CIA_CID_SHIFT) + cmp r3,r4 + bne 1b + + /* Found pcie, get regs and wrapper and save them */ + bl ai_get_slave + mov r8,r0 + bl ai_get_wrapper + mov r9,r0 + + /* Initialize memory controller and size memory */ + mov r0,r8 + mov r1,r9 + bl pcie_init + /* CA7 no need to do serdes and no socrom, skip it */ + cmp r7,r6 + beq init_ddr + + bl pcie_phy_init + +find_bootdev: + ldr r0,=SI_ENUM_BASE_DEFAULT /* r0: core regs SI base address */ + ldr r1,=CC_EROMPTR + ldr r1,[r0,r1] /* r1: erom pointer */ +1: ldr r2,[r1] /* r2: erom entry */ + ldr r3,=(ER_TAG | ER_VALID) + and r3,r3,r2 + cmp r3,#(ER_END | ER_VALID) /* Is this the END marker? */ + beq no_socrom_core /* Yes: done and did not find rom core */ + + cmp r3,#(ER_CI | ER_VALID) + beq 2f + + add r1,r1,#4 /* Next erom entry */ + b 1b + +no_socrom_core: + b init_ddr + + /* Found a CIA */ +2: add r1,r1,#8 /* Skip both CIA & CIB */ + ldr r3,=CIA_CID_MASK + and r3,r3,r2 + ldr r4,=(NS_ROM_CORE_ID << CIA_CID_SHIFT) + cmp r3,r4 + bne 1b + + /* Found socrom, get regs and wrapper and save them */ + bl ai_get_wrapper + ldr r1,[r0,#AI_IOSTATUS] + ldr r2,=SISF_NS_BOOTDEV_MASK + and r1,r1,r2 + mov r7,r1 + ldr r0,=SISF_NS_BOOTDEV_OFFLOAD + cmp r1,r0 + bne init_ddr + +offload_mode: + ldr r4,=0x1 + ldr r5,=0xffff042c + str r4,[r5] + ldr r4,=0x0 + ldr r5,=0xffff0430 +wait_for_host: + ldr r6,[r5] + cmp r6,r4 + beq wait_for_host + bx r6 + +/* + * Find ddr core + */ +init_ddr: + /* Identify CPU ID */ + mrc p15,0,r5,c0,c0,0 /* retrieve cpu part no */ + ldr r6,=CORTEX_ID_MASK + and r5,r5,r6 + ldr r6,=CORTEX_ID_A7 + +#ifdef CFG_SHMOO + cmp r5,r6 + beq ca7_copy2cache + + /* Copy to cache */ +copy2cache: + adrl r0,startup /* r0: source start address */ + ldr r1,=startup /* r1: target address */ + cmp r0,r1 + beq l2c_clear_bss + ldr r3,_bss_start_ofs + add r2,r0,r3 /* r2: source end address */ +l2c_copy_loop: + ldmia r0!,{r9-r10} /* copy from source address [r0] */ + stmia r1!,{r9-r10} /* copy to target address [r1] */ + cmp r0,r2 /* until source end address [r2] */ + blo l2c_copy_loop + + /* Clear BSS */ +l2c_clear_bss: + ldr r0,_bss_start_ofs + ldr r1,_bss_end_ofs + ldr r4,=startup + add r0,r0,r4 + add r1,r1,r4 + mov r2,#0x00000000 + /* empty bss section checking */ + cmp r0,r1 + beq enable_arm_cyclecount + +l2c_clbss_l: + str r2,[r0] + add r0,r0,#4 + cmp r0,r1 + bne l2c_clbss_l + +/* Cycle Count */ +enable_arm_cyclecount: + mrc p15,0,r1,c9,c12,0 + ldr r2,=1 + orr r1,r1,r2 + mcr p15,0,r1,c9,c12,0 /* Set enable bit in PMNC */ + ldr r1,=0x80000000 + mcr p15,0,r1,c9,c12,1 + + /* setup stack pointer */ + ldr r0,=0xc0000000 + ldr r1,=0x40000 /* 256KB */ + add r0,r0,r1 + sub r0,r0,#8 + mov sp,r0 + bic sp,sp,#7 + ldr r0,_c_ddr_init_ofs + ldr r1,=startup + add lr,r1,r0 + ldr r0,_c_ddr_init_done_ofs + adrl r1,startup + add r0,r1,r0 + mov pc,lr + b c_ddr_init_done + +ca7_copy2cache: + /* add CA7 shmoo c code handle here */ +c_ddr_init_done: +#else /* CFG_SHMOO */ + cmp r5,r6 + /* load CMEM_CORE_ID if CA7 */ + ldreq r4,=(CMEM_CORE_ID << CIA_CID_SHIFT) + /* load NS_DDR23_CORE_ID if CA9 */ + ldrne r4,=(NS_DDR23_CORE_ID << CIA_CID_SHIFT) + + ldr r0,=SI_ENUM_BASE_DEFAULT /* r0: core regs SI base address */ + ldr r1,=CC_EROMPTR + ldr r1,[r0,r1] /* r1: erom pointer */ +1: ldr r2,[r1] /* r2: erom entry */ + ldr r3,=(ER_TAG | ER_VALID) + and r3,r3,r2 + cmp r3,#(ER_END | ER_VALID) /* Is this the END marker? */ + beq panic /* Yes: done and did not find ddr */ + + cmp r3,#(ER_CI | ER_VALID) + beq 2f + + add r1,r1,#4 /* Next erom entry */ + b 1b + +panic: b . + + /* Found a CIA */ +2: add r1,r1,#8 /* Skip both CIA & CIB */ + ldr r3,=CIA_CID_MASK + and r3,r3,r2 + cmp r3,r4 + bne 1b + + /* Found ddr, get regs and wrapper and save them */ + bl ai_get_slave + mov r8,r0 + bl ai_get_wrapper + mov r9,r0 + + /* Initialize memory controller and size memory */ + mov r0,r8 + mov r1,r9 + mov r2,r7 /* boot_dev */ + + cmp r5,r6 + beq ca7_ddr_init + +ca9_ddr_init: + bl ddr_init_ca9 + ldr r6,=CORTEX_ID_A9 + b szmem + +ca7_ddr_init: + ldr r7,=0x18007400 + ldr fp,[r7] @ saved flag indicating DDR inited or not + bl ddr_init_ca7 + + ldr r0,=DDRC00_START + and r1,fp,r0 + cmp r1,r0 + beq ca7_cpu_boost_done @ don't boost CPU again in 2nd init DDR round + +ca7_cpu_boost_600MHz: + ldr r0,=0x18003000 @ switch ClockRatioARM 1:1 + ldr r1,[r0] + bic r1,r1,#(0x7<<9) + str r1,[r0] + + ldr r0,=0x18003000 @ switch ClockRatioCCI 1:1 + ldr r1,[r0] + bic r1,r1,#(0x3<<12) + str r1,[r0] + + ldr r0,=0x18012660 @ set CPU Fvco to 1.8G + ldr r1,=0xe + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,=0x01680000 + str r1,[r0] + + ldr r0,=0x18012660 @ set CPU channels 2,1,0 mdiv to 12:6:3, and pdiv to 1 + ldr r1,=0xd + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,=0x010c0603 + str r1,[r0] + + ldr r0,=0x18012660 @ set load_en for 3 channels + ldr r1,=0xc + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + orr r1,r1,#0x7000 + str r1,[r0] + + ldr r0,=0x18012600 @ update PLL with Fvco settings + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x1800002c @ wait until CPU PLL being locked + ldr r1,=0x1 +1: ldr r2,[r0] + and r2,r2,r1 + cmp r2,r1 + bne 1b + + ldr r0,=0x18012660 @ clear load_en for 3 channels + ldr r1,=0xc + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + bic r1,r1,#0x7000 + str r1,[r0] + + ldr r0,=0x18012600 @ set PLL control update bit + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x1800002c @ wait until CPU PLL being locked + ldr r1,=0x1 +1: ldr r2,[r0] + and r2,r2,r1 + cmp r2,r1 + bne 1b + + ldr r0,=0x18003000 @ boost CPU:CCI:NIC clock to 600:300:150 + ldr r1,[r0] + orr r1,r1,#(0x1<<12) @ switch ClockRatioCCI 2:1 + str r1,[r0] + ldr r1,[r0] + orr r1,r1,#(0x1<<9) @ switch ClockRatioArm 2:1 + str r1,[r0] + +ca7_cpu_boost_900MHz: + ldr r0,=0x18003000 @ switch ClockRatioARM 1:1 + ldr r1,[r0] + bic r1,r1,#(0x7<<9) + str r1,[r0] + + ldr r0,=0x18003000 @ switch ClockRatioCCI 1:1 + ldr r1,[r0] + bic r1,r1,#(0x3<<12) + str r1,[r0] + + ldr r0,=0x18012660 @ set CPU channels 2,1,0 mdiv to 12:6:2, and pdiv to 1 + ldr r1,=0xd + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + bic r1,r1,#0xff + orr r1,r1,#0x2 + str r1,[r0] + + ldr r0,=0x18012660 @ set load_en_ch for ch0 + ldr r1,=0xc + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + orr r1,r1,#0x1000 + str r1,[r0] + + ldr r0,=0x18012600 @ set PLL control update bit + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x1800002c @ wait until CPU PLL being locked + ldr r1,=0x1 +1: ldr r2,[r0] + and r2,r2,r1 + cmp r2,r1 + bne 1b + + /* FIXME. 53573B0 can't clear load_en when boot up to 900:300:150, + * otherwise it will hang when change CPU:CCI ratio. need to bypass + * "clear_load_en" codes below for 53573B0. + */ + + ldr r0,=SI_ENUM_BASE_DEFAULT + ldr r1,[r0] + ldr r2,=CID_REV_MASK + and r1,r1,r2 + lsr r1,r1,#CID_REV_SHIFT + cmp r1,#0x2 @ 53573B0 revid is 2 + bge ca7_cpu_set_ratio @ don't clear load_en if 53573B0 + + ldr r0,=0x18012660 @ clear load_en for ch0 + ldr r1,=0xc + str r1,[r0] + ldr r0,=0x18012664 + ldr r1,[r0] + bic r1,r1,#0x1000 + str r1,[r0] + + ldr r0,=0x18012600 @ set PLL control update bit + ldr r1,[r0] + orr r1,r1,#0x400 + str r1,[r0] + + ldr r0,=0x1800002c @ wait until CPU PLL being locked + ldr r1,=0x1 +1: ldr r2,[r0] + and r2,r2,r1 + cmp r2,r1 + bne 1b + +ca7_cpu_set_ratio: + ldr r0,=0x18003000 @ boost CPU:CCI:NIC clock to 900:300:150 + ldr r1,[r0] + orr r1,r1,#(0x1<<12) @ switch ClockRatioCCI 2:1 + str r1,[r0] + ldr r1,[r0] + orr r1,r1,#(0x2<<9) @ switch ClockRatioArm 3:1 + str r1,[r0] + +ca7_cpu_boost_done: + ldr r6,=CORTEX_ID_A7 +#endif /* CFG_SHMOO */ + +szmem: + ldr r3,=0x80000000 + ldr r2,=0xaa55beef + ldr r1,=0x00000000 + str r1,[r3,#0x70] + ldr r0,=(1 << 20) + ldr r5,=(1 << 30) + ldr r4,=CORTEX_ID_A7 + cmp r6,r4 + ldreq r5,=(1 << 29) @ 53573 DDR boundary 512M +1: + ldr r4,=0x80000000 + add r4,r4,r0 + str r2,[r4,#0x70] + ldr r1,[r4,#0x70] /* Read back to ensure completion */ + ldr r1,[r3,#0x70] + cmp r1,r2 + beq 2f + + lsl r0,r0,#1 + cmp r0,r5 + bne 1b + + /* Didn't find an alias, must be 128MB */ +2: + mov r8,r0 /* r8: the memory size in bytes */ + +/* Do CRU configure after DDR initied */ +#if !defined(CFG_ROMBOOT) + /* Identify CPU ID */ + mrc p15,0,r5,c0,c0,0 /* retrieve cpu part no */ + ldr r6,=CORTEX_ID_MASK + and r5,r5,r6 + ldr r6,=CORTEX_ID_A7 + cmp r5,r6 /* Cortex-A7? */ + beq poll_ccu_done +set_cru_policy7: + ldr r0,=IHOST_PROC_CLK_WR_ACCESS + ldr r1,=0xa5a501 + str r1,[r0] + + ldr r3,=SI_ENUM_BASE_DEFAULT + ldr r4,=CC_CHIPID + ldr r4,[r3,r4] + ldr r3,=CID_PKG_MASK + and r4,r4,r3 + lsr r3,r4,#CID_PKG_SHIFT + + cmp r3,#0 + beq cpu_1g + ldr r1,=0x1004001 /* 800MHz */ + b set_clocks + +cpu_1g: + ldr r1,=0x1005001 /* 1GHz */ + b set_clocks + +set_clocks: + ldr r0,=IHOST_PROC_CLK_PLLARMA + str r1,[r0] + ldr r2,=0x0 + + ldr r4,=0x100000 +poll_plllock: + cmp r4,r2 + beq poll_plllock_done + sub r4,r4,#1 + ldr r1,[r0] + and r3,r1,#(1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK) + cmp r3,r2 + beq poll_plllock +poll_plllock_done: + orr r1,r1,#(1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB) + str r1,[r0] + ldr r0,=IHOST_PROC_CLK_POLICY_FREQ + ldr r1,=0x87070707 + str r1,[r0] + ldr r0,=IHOST_PROC_CLK_CORE0_CLKGATE + ldr r1,=0x00010303 + str r1,[r0] + ldr r0,=IHOST_PROC_CLK_CORE1_CLKGATE + ldr r2,=0x00000303 + str r2,[r0] + ldr r0,=IHOST_PROC_CLK_ARM_SWITCH_CLKGATE + str r1,[r0] + ldr r0,=IHOST_PROC_CLK_ARM_PERIPH_CLKGATE + str r1,[r0] + ldr r0,=IHOST_PROC_CLK_APB0_CLKGATE + str r1,[r0] + + ldr r0,=IHOST_PROC_CLK_POLICY_CTL + ldr r2,=(1 << IHOST_PROC_CLK_POLICY_CTL__GO) + ldr r3,=(1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC) + orr r3,r3,r2 + str r3,[r0] + ldr r3,=0x0 + ldr r4,=0x100000 +poll_ccu: + cmp r4,r3 + beq poll_ccu_done + sub r4,r4,#1 + ldr r1,[r0] + and r1,r1,r2 + cmp r1,r3 + bne poll_ccu +poll_ccu_done: +#endif /* !defined(CFG_ROMBOOT) */ + +#ifndef CFG_SHMOO + /* Copy to RAM */ +copy2ram: + adrl r0,startup /* r0: source start address */ + ldr r1,=startup /* r1: target address */ + cmp r0,r1 + beq clear_bss + ldr r3,_bss_start_ofs + add r2,r0,r3 /* r2: source end address */ +copy_loop: + ldmia r0!,{r9-r10} /* copy from source address [r0] */ + stmia r1!,{r9-r10} /* copy to target address [r1] */ + cmp r0,r2 /* until source end address [r2] */ + blo copy_loop + + /* Clear BSS */ +clear_bss: + ldr r0,_bss_start_ofs + ldr r1,_bss_end_ofs + ldr r4,=startup + add r0,r0,r4 + add r1,r1,r4 + mov r2,#0x00000000 + /* empty bss section checking */ + cmp r0,r1 + beq enable_arm_cyclecount + +clbss_l: + str r2,[r0] + add r0,r0,#4 + cmp r0,r1 + bne clbss_l + +/* Cycle Count */ +enable_arm_cyclecount: + mrc p15,0,r1,c9,c12,0 + ldr r2,=1 + orr r1,r1,r2 + mcr p15,0,r1,c9,c12,0 /* Set enable bit in PMNC */ + ldr r1,=0x80000000 + mcr p15,0,r1,c9,c12,1 +#endif /* !CFG_SHMOO */ +/* Set stackpointer in internal RAM to call c_main */ +call_c_main: + /* Save memory size in bytes */ + mov r0,r8 + cmp r0,#(128<<20) + ble 1f + mov r0,#(128<<20) +1: + ldr r1,=_memsize + str r0,[r1] + +#ifdef _CFE_ + _LSR_ r8,r8,#10 /* memory size in Kbytes */ + ldr r1,=mem_totalsize + str r8,[r1] + + /* not relocating, no offset */ + ldr r0,=0 + ldr r1,=mem_datareloc + str r0,[r1] + ldr r1,=mem_textreloc + str r0,[r1] + + ldr r0,_text_start_ofs + add r0,r0,r4 + ldr r1,=mem_bottomofmem + str r0,[r1] + + ldr r0,__end_ofs + add r0,r0,r4 + ldr r1,=mem_heapstart + str r0,[r1] + + add r0,#(CFG_HEAP_SIZE*1024) + add r0,#STACK_SIZE + ldr r1,=mem_topofmem + str r0,[r1] + + ldr r0,_text_start_ofs + add r0,r0,r4 + ldr r2,_text_end_ofs + add r2,r2,r4 + sub r2,r2,r0 + ldr r1,=mem_textsize + str r2,[r1] + ldr r1,=mem_textbase + str r0,[r1] + + ldr r0,=0x00000000 + ldr r1,=cpu_prid + str r0,[r1] + + /* Set the segment_table */ + /* text_end */ + ldr r0,_text_end_ofs + add r0,r0,r4 + ldr r1,=segment_table + str r0,[r1] + + /* data_start */ + ldr r0,_data_start_ofs + add r0,r0,r4 + add r1,r1,#4 + str r0,[r1] + + /* data_end */ + ldr r0,_data_end_ofs + add r0,r0,r4 + add r1,r1,#4 + str r0,[r1] + + /* _end */ + ldr r0,__end_ofs + add r0,r0,r4 + add r1,r1,#4 + str r0,[r1] + + /* text_start */ + ldr r0,_text_start_ofs + add r0,r0,r4 + add r1,r1,#4 + str r0,[r1] + + /* bss_start */ + ldr r0,_bss_start_ofs + add r0,r0,r4 + add r1,r1,#4 + str r0,[r1] + + /* _gp (0) */ + mov r0,#0 + add r1,r1,#4 + str r0,[r1] + + /* RUNTIME_RELOC_START (0) */ + mov r0,#0 + add r1,r1,#4 + str r0,[r1] + + /* RUNTIME_RELOC_STOP (0) */ + mov r0,#0 + add r1,r1,#4 + str r0,[r1] + + /* cpu_apientry (0) */ + mov r0,#0 + add r1,r1,#4 + str r0,[r1] + + ldr r1,=mem_topofmem +#else /* !_CFE_ */ + ldr r1,=_memsize +#endif /* _CFE_ */ + + ldr r0,[r1] + sub r0,r0,#8 + mov sp,r0 + bic sp,sp,#7 /* 8-byte alignment for ABI compliance */ + + ldr r0,_c_main_ofs + ldr r1,=startup + add lr, r0, r1 + /* setup parameters for c_main */ +#ifdef _CFE_ + /* CFE: clear argument a & b in cfe_main */ + ldr r0,=0x00000000 + ldr r1,=0x00000000 +#else + /* CFEZ: set return addr to argment ra */ + ldr r0,_theend_ofs + add r0,r0,r2 +#endif + /* jump to it ... */ + mov pc,lr + +/* In case c_main returns */ +theend: + TRACE(0x424feedd) + wfe + b theend + +/* + * These are defined in the board-specific linker script. + */ + +#ifdef _CFE_ +.globl _text_start_ofs +_text_start_ofs: + .word text_start - startup + +.globl _text_end_ofs +_text_end_ofs: + .word text_end - startup + +.globl _data_start_ofs +_data_start_ofs: + .word data_start - startup + +.globl _data_end_ofs +_data_end_ofs: + .word data_end - startup + +.globl __end_ofs +__end_ofs: + .word _end - startup +#endif /* _CFE_ */ + +.globl _bss_start_ofs +_bss_start_ofs: + .word bss_start - startup + +.globl _bss_end_ofs +_bss_end_ofs: + .word bss_end - startup + +#ifdef CFG_SHMOO +_c_ddr_init_ofs: + .word c_ddr_init - startup + +_c_ddr_init_done_ofs: + .word c_ddr_init_done - startup +#endif /* CFG_SHMOO */ + +_c_main_ofs: + .word c_main - startup + +_theend_ofs: + .word theend - startup + +/* Init PCIE mappings */ +FUNC(pcie_init) + ldr r5,=REG_BAR2_CONFIG_F0 + str r5,[r0,#PAXB_INDR_ADDR] + ldr r3,[r0,#PAXB_INDR_DATA] + and r3,r3,#0xfffffff0 + orr r3,r3,#0xc + str r3,[r0,#PAXB_INDR_DATA] + + ldr r3,[r0,#PAXB_IARR_1_LOWER] + and r3,r3,#0xffffff00 + orr r3,r3,#0x80 + str r3,[r0,#PAXB_IARR_1_LOWER] + ldr r3,=0x40000000 + str r3,[r0,#PAXB_IARR_1_UPPER] + + ldr r3,=0x00000001 + str r3,[r0,#PAXB_FUNC0_IMAP1] + bx lr +END(pcie_init) + +/* + * Find the first slave address for a core in the AI EROM + * Input: + * r1 - pointer to EROM after CIB + * Output: + * r0 - slave address + * Changed: + * r0, r1, r2 + */ +FUNC(ai_get_slave) +1: ldr r0,[r1] + ldr r2,=(ER_TAG | ER_VALID) + add r1,r1,#4 /* Next erom entry */ + and r2,r2,r0 + cmp r2,#(ER_ADD | ER_VALID) + bne 1b + +2: ldr r2,=AD_ADDR_MASK + and r0,r0,r2 + bx lr +END(ai_get_slave) + +/* + * Find the first wrapper address for a core in the AI EROM + * Input: + * r1 - pointer to EROM after first slave ADD + * Output: + * r0 - wrapper address + * Changed: + * r0, r1, r2, r3 + */ +FUNC(ai_get_wrapper) +1: ldr r0,[r1] + ldr r2,=(ER_TAG | ER_VALID) + add r1,r1,#4 /* Next erom entry */ + and r2,r2,r0 + cmp r2,#(ER_ADD | ER_VALID) + bne 1b + + /* An address descriptor, is it a wrapper? */ + ldr r2,=AD_ST_SWRAP /* We test just for the SWRAP bit set, */ + tst r0,r2 /* that gets both Master and Slave */ + beq 1b /* wrappers. */ + + /* It is, isolate address and return */ + ldr r2,=AD_ADDR_MASK + and r0,r0,r2 + bx lr +END(ai_get_wrapper) + +/* Interrupt handlers */ +/* Note: hnd_rte_arm.c for EXT_CBALL expects each trap handler to be 16 bytes */ +LEAF(__traps) + +/* Undefined instruction exception handler */ +tr_und: + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + /* now cr4 is in system mode */ + /* lr has the value before the exception, push it to stack */ + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} /* save r0-r7 to the stack */ + eor r0,r0,r0 + add r0,r0,#TR_UND + b trap + +/* Software interrupt exception handler */ +tr_swi: + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} + eor r0,r0,r0 + add r0,r0,#TR_SWI + b trap + +/* Prefetch abort exception handler */ +tr_iab: + /* adjust lr to the address of abort insturction fetch */ + mov sp,lr + sub sp,sp,#4 + mov lr,sp + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} + eor r0,r0,r0 + add r0,r0,#TR_IAB + b trap + +/* Data abort exception handler */ +tr_dab: + /* adjust lr to the address of aborted data fetch */ + mov sp,lr + sub sp,sp,#8 + mov lr,sp + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} + eor r0,r0,r0 + add r0,r0,#TR_DAB + b trap + +tr_bad: /* reserved */ + mov sp,lr + sub sp,sp,#4 + mov lr,sp + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} + eor r0,r0,r0 + add r0,r0,#TR_BAD + b trap + +/* Interrupt handler */ +tr_irq: + /* subtract the offset */ + mov sp,lr + sub sp,sp,#4 + mov lr,sp + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} + eor r0,r0,r0 + add r0,r0,#TR_IRQ + b trap + +/* Fast interrupt handler */ +tr_fiq: + mov sp,lr + sub sp,sp,#4 + mov lr,sp + srsdb sp!, #PS_SYS /* use system mode stack */ + cps #PS_SYS + + push {r0} /* hold the place for r15 */ + push {lr} + sub sp,sp,#24 /* skip r8-r13 now */ + push {r0-r7} + eor r0,r0,r0 + add r0,r0,#TR_FIQ + b trap + +/* Generic exception handler */ +trap: + /* + * construt the trap structure in system mode stack + */ + /* save trap type, epc, cpsr and spsr */ + mov r4, sp /* sp is now at r0 */ + add r4,r4,#64 + ldmia r4!, {r1,r3} /* r1<-epc, r3<-spsr */ + mrs r2, cpsr + push {r0,r1,r2,r3} /* trap type(r0), epc(r1), cpsr,spsr */ + + /* fix the value of pc in trap structure */ + sub r4,r4,#12 + str r1,[r4] /* save the value or epc as r15 into the stack */ + + /* save r8 - r13 */ + mov r7,sp /* sp is at the being of the trap structure now */ + add r7,r7,#TRAP_T_SIZE + 8 /* sp value before the exception */ + mov r6,r12 + mov r5,r11 + mov r4,r10 + mov r3,r9 + mov r2,r8 + add sp,sp,#72 /* move sp to r14 */ + push {r2-r7} /* save r8-r13 to stack */ + + sub sp,sp,#48 /* move sp back to the top of trap structure */ + + /* If trap_hook is null, go to the end */ + ldr r4,=trap_hook + ldr r4,[r4] + cmp r4,#0 +1: beq 1b + /* else call (*trap_hook)(trap_t) */ + mov r0,sp + blx r4 + +/* Restore the state from the trap_t */ +rfe: + /* pop r8-r14 */ + add sp,sp,#48 + pop {r0-r6} /* r8 - r14 */ + mov r8,r0 + mov r9,r1 + mov r10,r2 + mov r11,r3 + mov r12,r4 + mov lr,r6 /* restore lr */ + + sub sp,sp,#60 /* move sp to point to r0 */ + pop {r0-r7} + + /* move sp to point to epc and spsr saved by srs */ + add sp,sp,#32 + + /* Restore cpsr, sp and return */ + rfeia sp! /* done! */ +END(__traps) + +FUNC(_getticks) + mrc p15,0,r0,c9,c13,0 + bx lr +END(_getticks) + +/* Flush the whole D-cache */ +cpu_flush_dcache_all: + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +loop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop2: + mov r9, r4 @ create working copy of max way size +loop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge loop3 + subs r7, r7, #1 @ decrement the index + bge loop2 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt loop1 +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mov pc, lr + +FUNC(cpu_flush_cache_all) + stmfd sp!, {r0-r7, r9-r11, lr} + bl cpu_flush_dcache_all + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + ldmfd sp!, {r0-r7, r9-r11, lr} + mov pc, lr +END(cpu_flush_cache_all) + +/* Invalidate the whole D-cache */ +cpu_inv_dcache_all: + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq invfinished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +invloop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt invskip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +invloop2: + mov r9, r4 @ create working copy of max way size +invloop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge invloop3 + subs r7, r7, #1 @ decrement the index + bge invloop2 +invskip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt invloop1 +invfinished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mov pc, lr + +FUNC(cpu_inv_cache_all) + stmfd sp!, {r0-r7, r9-r11, lr} + bl cpu_inv_dcache_all + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + ldmfd sp!, {r0-r7, r9-r11, lr} + mov pc, lr +END(cpu_inv_cache_all) + +/* Dummy function just for link happy */ +FUNC(raise) + + mov r0, #0 + mov pc, lr + +END(raise) + +FUNC(__aeabi_unwind_cpp_pr0) + + mov pc, lr + +END(__aeabi_unwind_cpp_pr0) + +/* + * Common code/data start here... + */ +#ifdef CONFIG_XIP + .data +#endif + + DW(_memsize, 0) + +/* C trap handler */ + DW(trap_hook, 0) + +#ifdef CONFIG_XIP + .text +#endif + +#ifdef _CFE_ + +/* + * Setup the trap handler. + */ +FUNC(hnd_set_trap) + + ldr r2,=trap_hook + ldr r1,[r2] + str r0,[r2] + mov r0,r1 + bx lr + +END(hnd_set_trap) + +/* + * Turn remap off and then jump to an given address + */ +FUNC(arm_jumpto) + + bx r0 + +END(arm_jumpto) + +/* ********************************************************************* + * CFE_FLUSHCACHE + * + * Perform certain cache operations + * + * Input parameters: + * a0 - flags (CFE_CACHE_xxx flags, or zero for a default) + * a1,a2 - start/end of range for "range invalidate" operations + * (not used otherwise) + * + * Return value: + * nothing + ********************************************************************* */ + +FUNC(_cfe_flushcache) + +#ifndef CFG_UNCACHED + mov ip,lr /* save lr across calls */ + bl cpu_flush_cache_all + mov lr,ip /* restore lr */ +#endif + + mov pc, lr + +END(_cfe_flushcache) + +# +# arguments: r0=start, r1=size +# +FUNC(_cfe_flushcache_rang) + + mrc p15, 1, r3, c0, c0, 0 @ read CSIDR + and r3, r3, #7 @ cache line size encoding + mov r2, #16 @ size offset + mov r2, r2, lsl r3 @ actual cache line size + + sub r3, r2, #1 + bic r0, r0, r3 +1: + mcr p15, 0, r0, c7, c10, 1 @ clean D / U line + add r0, r0, r2 + cmp r0, r1 + blo 1b +# dsb + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mov pc, lr + +END(_cfe_flushcache_rang) + +/* ********************************************************************* + * CFE_LAUNCH + * + * Start the user program. The program is passed a handle + * that must be passed back when calling the firmware. + * + * Parameters passed to the called program are as follows: + * + * a0 - CFE handle + * a1 - entry vector + * a2 - reserved, will be 0 + * a3 - entrypoint signature. + * + * Input parameters: + * a0 - entry vector + * + * Return value: + * does not return + ********************************************************************* */ + +FUNC(cfe_launch) + + sub sp,sp,#8 + push {r0} + + /* + * Mask all interrupts. + */ + + mrs r0,cpsr + ldr r1,=(PS_I | PS_F) + orr r0,r0,r1 + msr cpsr,r0 + + /* + * Flush the D-Cache, since the program we loaded is "data". + * Invalidate the I-Cache, so that addresses in the program + * region will miss and need to be filled from the data we + * just flushed above. + */ + + bl _cfe_flushcache + + /* + * Disable the D-Cache, MMU and I-Cache bit + */ + + mrc p15,0,r0,c1,c0,0 @ read SCTLR + bic r0,r0,#4 @ disable D-Cache + bic r0,r0,#1 @ disable MMU + bic r0,r0,#1000 @ disable I-Cache + mcr p15,0,r0,c1,c0,0 + + /* + * Set things up for launching the program. Pass the + * handle in A0 - apps need to remember that and pass it + * back. + */ + b RunProgram + +END(cfe_launch) + +/* + * This is a nice place to set a breakpoint. + */ +FUNC(RunProgram) + + LOADREL(r2,=segment_table) + ldr r2,[r2,#R_SEG_APIENTRY] /* A2 = code entry */ + +#if CFG_EMBEDDED_PIC + ldr r1,mem_textreloc /* relocate table entry */ + add r2,r2,r1 +#endif + + mov r4,r0 + mov r1,#0 /* A1 = 0 */ + mov r0,#0 /* A0 = handle */ + ldr r3,=CFE_EPTSEAL /* A3 = entrypoint signature */ + pop {r4} /* entry point */ + + /* Check if the MERGE_FRAG function should execute or not, + * according to the information within structure cfe_frag_info_t. + * _frag_info_sz is the size of structure cfe_frag_info_t. + * Structure cfe_frag_info_t is stored right before MERGE_FRAG function, and + * MERGE_FRAG function is stored right before entry point. + * Note: {r0-r4} must be preserved + */ + ldr r7, =_frag_merge_func_len + ldr r6, [r7] + ldr r8, =_frag_info_sz + ldr r7, [r8] + add r6, r6, r7 + sub r5, r4, r6 + ldr r6, [r5] + cmp r6, #0 + beq do_run + mov pc, r6 /* Go to _merge_func */ +do_run: + mov pc, r4 /* go for it. */ +END(RunProgram) + + .globl _frag_merge_func +_frag_merge_func: + .word _merge_func + + .globl _frag_merge_func_len +_frag_merge_func_len: + .word _merge_func_end - _merge_func + + .globl _frag_info_sz +_frag_info_sz: + .word 0 + +/* This merge_func will relocate at address which is stored at MERGE_FRAG. + * It will reference the value which is stored at MERGE_FRAG. + * There are the merge_func pointer, des_addr, src_addr and length. + * r4 is the entry point, r0-r3 are the parameters for the image. + * r5 is the address of MERGE_FRAG + */ +FUNC(_merge_func) + ldmia r5, {r9-r12} +1: + ldmia r11!, {r7-r8} @ copy 8 bytes from the memory at r11 address + stmia r10!, {r7-r8} @ store 8 bytes to the memory at r10 address + @ r12 is the length, each loop copy 8 bytes + subs r12, r12, #8 @ adjust the length + bgt 1b + + mov pc, r4 @ jump to the entry point +_merge_func_end: +END(_merge_func) + +/* ********************************************************************* + * BOARD_SETLEDS(x) + * + * Set LEDs for boot-time progress indication. Not used if + * the board does not have progress LEDs. This routine + * must not call any other routines, since it may be invoked + * either from KSEG0 or KSEG1 and it may be invoked + * whether or not the icache is operational. + * + * Input parameters: + * a0 - LED value (8 bits per character, 4 characters) + * + * Return value: + * nothing + ********************************************************************* */ +FUNC(board_setleds) + + mov pc, lr @ back to my caller + +END(board_setleds) + +/* ********************************************************************* + * CFE_LEDS + * + * Set the on-board LEDs. + * + * Input parameters: + * a0 - LEDs + * + * Return value: + * nothing + ********************************************************************* */ +FUNC(cfe_leds) + + /* jump to BSP routine */ + //bl board_setleds + + /* return */ + mov pc, lr + +END(cfe_leds) + +/* ********************************************************************* + * _GETSEGTBL() + * + * Return the address of the segment table. We use this + * to display the startup messages. + * + * You can't just address the table from C because it lives + * in the text segment. + * + * Input parameters: + * nothing + * + * Return value: + * address of table + ********************************************************************* */ + +FUNC(_getsegtbl) + + mov ip, lr /* persevere link reg across call */ + LOADREL(r0,=segment_table) + mov lr, ip /* restore link */ + mov pc, lr /* back to my caller */ + +END(_getsegtbl) + +/* ********************************************************************* + * _SETCONTEXT() + * + * Set the CONTEXT register. + * + * Input parameters: + * a0 - context + * + * Return value: + * nothing + ********************************************************************* */ + +FUNC(_setcontext) + + mov pc,lr + +END(_setcontext) + +/* ********************************************************************* + * CFE_WARMSTART + * + * Restart the command interpreter + * + * Input parameters: + * A0 - command status + * nothing (GP has already been set up for us) + * + * Return value: + * nothing + ********************************************************************* */ + +FUNC(cfe_warmstart) + + mov pc,lr + +END(cfe_warmstart) + +#endif /* _CFE_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Bcmbuild.mk new file mode 100644 index 00000000000..e6ebf274a79 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Bcmbuild.mk @@ -0,0 +1,69 @@ +LIB := libbcmmcast.so + +all install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH := $(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_INSTALL_KERNEL_HDR_PATH)/include + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR +export BRCM_OVS_SUPPORT_MCAST + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + + +ifneq ($(strip $(BUILD_MCAST_SNOOP)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + +else + +conditional_build: + @echo "Skipping $(LIB) (not configured)" + +endif + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Makefile new file mode 100644 index 00000000000..702bfc94186 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Makefile @@ -0,0 +1,13 @@ + +LIB = libbcmmcast.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Makefile.fullsrc new file mode 100644 index 00000000000..87935f3a9d8 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/Makefile.fullsrc @@ -0,0 +1,36 @@ +OBJS := bcm_mcast_api.o + +#CFLAGS += -Werror -Wfatal-errors + +ifneq ($(strip $(BRCM_OVS_SUPPORT_MCAST)),) +CFLAGS += -DCONFIG_BCM_OVS_MCAST +endif + +# These are public API headers needed by other apps which want to call this lib. +# Private/internal headers should not be listed here. +HEADERS := + +# from Bcmbuild.mk +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include + +all: $(LIB) + mkdir -p $(HEADER_INSTALL_DIR) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive + + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(addprefix $(HEADER_INSTALL_DIR)/,$(HEADERS)) + +binaryonly_prepare: + -cp $(LIB) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ -I$(HND_SRC)/userspace/public/include/ -I$(HND_SRC)/kernel/bcmkernel/include/uapi/ +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/autodetect new file mode 100644 index 00000000000..e69de29bb2d diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/prebuilt/libbcmmcast.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/prebuilt/libbcmmcast.so new file mode 100755 index 00000000000..238d784d2c2 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcast/prebuilt/libbcmmcast.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Bcmbuild.mk new file mode 100644 index 00000000000..cdd789edc47 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Bcmbuild.mk @@ -0,0 +1,84 @@ +EXE := bcmmcastctl +EXEALT := bmc + +all install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + +ifneq ($(strip $(BRCM_VOICE_SUPPORT)),) +include $(BUILD_DIR)/make.voice +endif + + +ARCH := $(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/bin +ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR + + +# Remove all mdm_cbk_* and bcm_*_hal libs from CMS_CORE_LIBS. The local +# Makefile will specify which mdm_cbk and hal libs it needs. +MDM_CORE_LIBS := $(patsubst -lmdm_cbk_%,,$(CMS_CORE_LIBS)) +MDM_CORE_LIBS := $(patsubst -lbcm_%_hal,,$(MDM_CORE_LIBS)) + +export CMS_COMMON_LIBS MDM_CORE_LIBS + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin$(BCM_INSTALL_SUFFIX_DIR) + + +ifneq ($(strip $(BUILD_MCAST_SNOOP)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + (cd $(FINAL_EXE_INSTALL_DIR); ln -sf $(EXE) $(EXEALT)) + +else + +conditional_build: + @echo "Skipping $(EXE) (not configured)" + +endif + + +clean: clean_legacy + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(EXE) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Makefile new file mode 100644 index 00000000000..3bccc7537ca --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Makefile @@ -0,0 +1,15 @@ + +EXE = bcmmcastctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + mkdir -p $(INSTALL_DIR)/bin + (cd $(INSTALL_DIR)/bin; rm -f bmc; ln -s $(EXE) bmc) + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Makefile.fullsrc new file mode 100644 index 00000000000..8a11d32a9c2 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/Makefile.fullsrc @@ -0,0 +1,21 @@ +OBJS := bcm_mcast_ctl.o + +LIBS := -L$(HND_SRC)/router-sysdep/bcmmcast/ -lbcmmcast + +CFLAGS += -Werror -Wfatal-errors + + +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + ln -sf bcmmcastctl bmc + + +binaryonly_prepare: + -cp $(EXE) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ -I$(HND_SRC)/userspace/public/include/ +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/autodetect new file mode 100644 index 00000000000..20cb79f033c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/autodetect @@ -0,0 +1,2 @@ +dependson: private/libs/bcmmcast + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/prebuilt/bcmmcastctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/prebuilt/bcmmcastctl new file mode 100755 index 00000000000..c36c6a56b8f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmmcastctl/prebuilt/bcmmcastctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/Makefile new file mode 100644 index 00000000000..46b19987fbb --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/Makefile @@ -0,0 +1,15 @@ + +EXE = bcmtmctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + mkdir -p $(INSTALL_DIR)/bin + (cd $(INSTALL_DIR)/bin; rm -f bcmtm; ln -s $(EXE) bcmtm) + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/Makefile.fullsrc new file mode 100644 index 00000000000..d83fb4356e5 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/Makefile.fullsrc @@ -0,0 +1,80 @@ +# +# Makefile for BCM Traffic Manager Control Utility. +# Program Executable: bcmtmctl +# Set custom variables in this first section +# +EXE = bcmtmctl +OBJS = bcm_tm_ctl.o +LIBS = -lbcmtm + +PROGRAM_NAME_ALT:=bcmtm + +all dynamic install: $(EXE) generic_exe_install + ln -sf $(EXE) $(INSTALL_DIR)/bin/$(PROGRAM_NAME_ALT) + +clean: generic_clean + rm -f $(OBJS) + rm -f $(INSTALL_DIR)/bin/$(EXE) + rm -f $(INSTALL_DIR)/bin/$(PROGRAM_NAME_ALT) + +binaryonly_dist_clean: clean generic_binaryonly_dist_clean + rm -f Makefile.fullsrc + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) + +include $(BUILD_DIR)/make.common + +# +# Private apps and libs are allowed to include header files from the +# private and public directories. +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + + +# +# Private apps and libs are allowed to link with libraries from the +# private and public directories. +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/autodetect new file mode 100644 index 00000000000..68860988ab8 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/autodetect @@ -0,0 +1,4 @@ + +dependson: private/libs/bcmtm +condition: ifneq ($(strip $(BUILD_BCMTM)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/prebuilt/bcmtmctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/prebuilt/bcmtmctl new file mode 100755 index 00000000000..346d4f87428 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm/prebuilt/bcmtmctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/Makefile new file mode 100644 index 00000000000..8da822c5e9b --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/Makefile @@ -0,0 +1,13 @@ + +LIB = libbcmtm.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/autodetect new file mode 100644 index 00000000000..ca37431375c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/autodetect @@ -0,0 +1,3 @@ + +condition: ifneq ($(strip $(BUILD_BCMTM)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/prebuilt/libbcmtm.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/prebuilt/libbcmtm.so new file mode 100755 index 00000000000..0b4a9a37de6 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bcmtm_lib/prebuilt/libbcmtm.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/Makefile new file mode 100644 index 00000000000..6f0b9859494 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/Makefile @@ -0,0 +1,76 @@ +# +# In most cases, you only need to modify this first section. +# +LIB = libbdmf.so + +OBJS = bdmf_user.o + +all dynamic install: conditional_build + +clean: generic_clean + rm -f $(INSTALL_DIR)/lib/public/$(LIB) + + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# You do not need to modify this part. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) + +include $(BUILD_DIR)/make.common + +ifneq ($(strip $(BUILD_RDPA)),) +conditional_build: generic_public_lib_install +else +conditional_build: + @echo "skipping $(LIB) (not configured)" +endif + +# +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/shared/opensource/include/bcm963xx \ + -I$(PROJECT_DIR)/target/bdmf/system \ + -I$(PROJECT_DIR)/target/bdmf/system/sim \ + -I$(PROJECT_DIR)/target/rdpa_user \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + $(INC_RDP_FLAGS) + +CFLAGS += -Werror + + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# +ifneq ($(wildcard prebuilt/libbdmf.so),) +$(LIB): + cp prebuilt/libbdmf.so ./libbdmf.so +else +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive $(LOCAL_LDFLAGS) +endif + + + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/autodetect new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/autodetect @@ -0,0 +1 @@ + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/bdmf_user.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/bdmf_user.c new file mode 100644 index 00000000000..633a5266b91 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_lib/bdmf_user.c @@ -0,0 +1,262 @@ +/* +<:copyright-BRCM:2019:DUAL/GPL:standard + + Copyright (c) 2019 Broadcom + All Rights Reserved + +Unless you and Broadcom execute a separate written software license +agreement governing use of this software, this software is licensed +to you under the terms of the GNU General Public License version 2 +(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, +with the following added to such license: + + As a special exception, the copyright holders of this software give + you permission to link this software with independent modules, and + to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent + module, the terms and conditions of the license of that module. + An independent module is a module which is not derived from this + software. The special exception does not apply to any modifications + of the software. + +Not withstanding the above, under no circumstances may you combine +this software in any way with any other Broadcom software provided +under a license other than the GPL, without Broadcom's express prior +written consent. + +:> +*/ + +#include +#include +#include "bdmf_user_interface.h" + +static int call_ioctl(bdmf_ioctl_t *ba, int cmd) +{ + int fd, ret = 0; + + fd = open(RDPA_USR_DEV_NAME, O_RDWR); + if (fd < 0) + { + rdpa_usr_error("%s: %s\n", RDPA_USR_DEV_NAME, strerror(errno)); + return -EINVAL; + } + + ret = ioctl(fd, cmd, (uintptr_t)ba); + if (ret) + rdpa_usr_error("ioctl failed, ret=%d\n", ret); + + close(fd); + return ret; +} + +int bdmf_new_and_set(bdmf_type_handle drv, + bdmf_object_handle owner, + const bdmf_mattr_handle hmattr, + bdmf_object_handle *pmo) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.drv = drv; + ba.owner_or_ds = owner; + ba.mattr = hmattr; + + ret = call_ioctl(&ba, BDMF_NEW_AND_SET); + if (ret) + return -EINVAL; + + *pmo = ba.mo_or_us; + return ba.ret; +} + +int bdmf_destroy(bdmf_object_handle mo) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.mo_or_us = mo; + + ret = call_ioctl(&ba, BDMF_DESTROY); + if (ret) + return -EINVAL; + + return ba.ret; +} + +bdmf_mattr_handle bdmf_mattr_alloc(bdmf_type_handle drv) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.drv = drv; + + ret = call_ioctl(&ba, BDMF_MATTR_ALLOC); + if (ret) + return 0; + + return ba.mattr; +} + +void bdmf_mattr_free(bdmf_mattr_handle mattr) +{ + bdmf_ioctl_t ba; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.mattr = mattr; + + call_ioctl(&ba, BDMF_MATTR_FREE); +} + +void bdmf_get(bdmf_object_handle mo) +{ + bdmf_ioctl_t ba; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.mo_or_us = mo; + + call_ioctl(&ba, BDMF_GET); +} + +void bdmf_put(bdmf_object_handle mo) +{ + bdmf_ioctl_t ba; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.mo_or_us = mo; + + call_ioctl(&ba, BDMF_PUT); +} + +bdmf_object_handle bdmf_get_next(bdmf_type_handle drv, + bdmf_object_handle mo, const char *filter) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.drv = drv; + ba.mo_or_us = mo; + ba.str = filter; + + + ret = call_ioctl(&ba, BDMF_GET_NEXT); + if (ret) + return 0; + + return ba.owner_or_ds; +} + +int bdmf_link(bdmf_object_handle ds, + bdmf_object_handle us, const char *attrs) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.owner_or_ds = ds; + ba.mo_or_us = us; + ba.str = attrs; + + ret = call_ioctl(&ba, BDMF_LINK); + if (ret) + return -EINVAL; + + return ba.ret; +} + +int bdmf_unlink(bdmf_object_handle ds, bdmf_object_handle us) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.owner_or_ds = ds; + ba.mo_or_us = us; + + ret = call_ioctl(&ba, BDMF_UNLINK); + if (ret) + return -EINVAL; + + return ba.ret; +} + + +bdmf_link_handle bdmf_get_next_us_link(bdmf_object_handle mo, + bdmf_link_handle prev) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.owner_or_ds = mo; + ba.link = prev; + + ret = call_ioctl(&ba, BDMF_GET_NEXT_US_LINK); + if (ret) + return 0; + + return ba.link; +} + +bdmf_link_handle bdmf_get_next_ds_link(bdmf_object_handle mo, + bdmf_link_handle prev) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.mo_or_us = mo; + ba.link = prev; + + ret = call_ioctl(&ba, BDMF_GET_NEXT_DS_LINK); + if (ret) + return 0; + + return ba.link; +} + +bdmf_object_handle bdmf_us_link_to_object(bdmf_link_handle us_link) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.link = us_link; + + ret = call_ioctl(&ba, BDMF_US_LINK_TO_OBJECT); + if (ret) + return 0; + + return ba.mo_or_us; +} + +bdmf_object_handle bdmf_ds_link_to_object(bdmf_link_handle ds_link) +{ + bdmf_ioctl_t ba; + int ret = 0; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.link = ds_link; + + ret = call_ioctl(&ba, BDMF_DS_LINK_TO_OBJECT); + if (ret) + return 0; + + return ba.owner_or_ds; +} + +void bdmf_get_owner(const bdmf_object_handle mo, + bdmf_object_handle *owner) +{ + bdmf_ioctl_t ba; + + memset(&ba, 0x0, sizeof(bdmf_ioctl_t)); + ba.mo_or_us = mo; + + call_ioctl(&ba, BDMF_GET_OWNER); + *owner = ba.owner_or_ds; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/Makefile new file mode 100644 index 00000000000..908031e3450 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/Makefile @@ -0,0 +1,51 @@ +# This Makefile builds bdmf_shell application that enables +# CLI capabilities in BDMF-based management system (ie, RDPA) +# +EXE=bdmf_shell +OBJS=bdmf_shell_client.o +LIBS = -lpthread + +all dynamic install: build + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +BDMF_DIR=$(BRCMDRIVERS_DIR)/opensource/char/bdmf/bcm9$(BRCM_CHIP) + +include $(BUILD_DIR)/make.common + +ALLOWED_INCLUDE_PATHS := -I. +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public +CUSTOM_CFLAGS += -Werror -Wfatal-errors -DBDMF_SYSTEM_LINUX $(INC_RDP_FLAGS) + +SCRIPT_FILE=scripts/xrdp_hw_accel_dump.sh +ifneq ($(findstring _$(strip $(BRCM_CHIP))_,_63138_63148_4908_),) + SCRIPT_FILE=scripts/rgen30_hw_accel_dump.sh +endif +ifneq ($(findstring _$(strip $(BRCM_CHIP))_,_63146_4912_6855_6813_),) + SCRIPT_FILE=scripts/rgen61_hw_accel_dump.sh +endif + +ifneq ($(strip $(BUILD_BDMF_SHELL)),) +build: $(EXE) generic_exe_install + install scripts/rdpa_init.sh $(INSTALL_DIR)/rom/rom/etc + install scripts/bs $(INSTALL_DIR)/bin + install scripts/bsi $(INSTALL_DIR)/bin + install scripts/runner $(INSTALL_DIR)/bin + install scripts/runner_dump.sh $(INSTALL_DIR)/bin + install $(SCRIPT_FILE) $(INSTALL_DIR)/bin/hw_accel_dump.sh +else +build: + @echo "skipping $@ (not configured)" +endif + +ifneq ($(wildcard prebuilt/bdmf_shell),) +$(EXE): + cp prebuilt/bdmf_shell ./bdmf_shell +else +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) $(LIBS) +endif + +clean: generic_clean + rm -f $(INSTALL_DIR)/bin/$(EXE) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/autodetect new file mode 100644 index 00000000000..6dcd3239817 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/autodetect @@ -0,0 +1,2 @@ +dependson: public/libs/cms_msg public/libs/cms_util public/libs/bcm_flashutil public/libs/bcm_boardctl + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/bdmf_shell_client.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/bdmf_shell_client.c new file mode 100644 index 00000000000..84511e01c71 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/bdmf_shell_client.c @@ -0,0 +1,527 @@ +/*********************************************************************** + * <:copyright-BRCM:2011-2015:DUAL/GPL:standard + * + * Copyright (c) 2011-2015 Broadcom + * All Rights Reserved + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2 + * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, + * with the following added to such license: + * + * As a special exception, the copyright holders of this software give + * you permission to link this software with independent modules, and + * to copy and distribute the resulting executable under terms of your + * choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. + * An independent module is a module which is not derived from this + * software. The special exception does not apply to any modifications + * of the software. + * + * Not withstanding the above, under no circumstances may you combine + * this software in any way with any other Broadcom software provided + * under a license other than the GPL, without Broadcom's express prior + * written consent. + * + * :> + ************************************************************************/ + +/******************************************************************* + * bdmf_mon_client.c + * + * BDMF framework - remote shell client + * + * This file is compiled into independent application + *******************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* to get htonl, ntohl */ +#include /* to get inet_aton and friends */ +#include +#include +#include +#ifndef BDMF_SYSTEM_SIM +#include "bdmf_chrdev.h" +#endif + +/* #define DEBUG */ +#ifdef DEBUG +#define dprintf(fmt, ...) printf("%s#%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define dprintf(...) +#endif + + +static int client_sock; +static pthread_t rx_thread; +static pthread_t cli_output_thread; +static int rx_thread_killed; +static int serial_file; /* serial file handle */ +static int session_id = -1; /* serial session id */ +static int cmd_rc; +struct termios orig_termios; + +#define BDMF_SERIAL_FILE_NAME "/dev/bdmf_shell" +#define BDMF_MAX_LINE_LENGTH 2048 + +/* Receive handler */ +static void *bdmfmons_client_thread_handler(void *arg __attribute__((unused))) +{ + char ch; + + while (recv(client_sock, &ch, 1, MSG_WAITALL) > 0) + putchar(ch); + + rx_thread_killed = 1; + return NULL; +} + +static void *bdmfmons_cli_output_thread_handler(void *arg __attribute__((unused))) +{ + char ch; + int rc; + + while ((rc = read(serial_file, &ch, 1)) > 0) + { + putchar(ch); + fflush(stdout); + } + + printf("CLI output thread tereminated. rc=%d errno=%s(%d)\n", + rc, strerror(errno), errno); + + return NULL; +} + +static int print_help(int print_usage, char *msg, ...) + __attribute__((format(printf, 2, 3))); +static int print_help(int print_usage, char *msg, ...) +{ + if (msg) + { + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + } + if (print_usage) + { + fprintf(stderr, "Usage:\n" + "\tbdmf_shell server_addr:port [options]\n" + "\tbdmf_shell domain_socket_addr [options]\n" + "\tbdmf_shell [-c init | session_id] [-cmd command] [-f script_file] [-fg] [-close]\n" + "\t\t-c : serial communication. Must be followed by \"init\" or session_id\n" + "\t\t-cmd command : send BDMF shell command\n" + "\t\t-f script_file : send script_file content\n" + "\t\t-fg - interactive mode\n" + "\t\t-close - close session opened by \"-c init\" - used with \"-c\"\n" + ); + } + return -1; +} + +static int open_socket_channel(int protocol, struct sockaddr *sa, int len) +{ + int rc; + char ch; + + /* Create and connect socket */ + client_sock = socket(protocol, SOCK_STREAM, 0); + if ((client_sock < 0)) + { + perror("socket"); + exit(-3); + } + if (connect(client_sock, sa, len)<0) + { + perror("connect"); + exit(-4); + } + + /* initiate conversation in order to bind */ + ch = '\n'; + if (send(client_sock, &ch, 1, 0)<=0) + return print_help(0, "failed to initiate conversation\n"); + + /* connected and ready. + * Now + * - create rx thread that will wait for rx from the socket and print to stdout + * - start reading from stdin and sending to the socket + */ + rc = pthread_create(&rx_thread, NULL, bdmfmons_client_thread_handler, NULL); + if (rc) + return print_help(0, "failed to create rx thread\n"); + return 0; +} + + +static int init_serial_session(void) +{ +#ifndef BDMF_SYSTEM_SIM + struct io_param iop; + /* Open new serial session */ + if (ioctl(serial_file, BDMF_CHRDEV_SESSION_INIT, &iop) == -1) + { + perror("init session"); + return -1; + } + session_id = iop.session_id; + printf("Session: %d\n", session_id); +#endif + return session_id; +} + +static int close_serial_session(void) +{ +#ifndef BDMF_SYSTEM_SIM + struct io_param iop; + if (session_id < 0) + return print_help(0, "Can't close session. session_id is missing\n"); + /* Close serial session */ + iop.session_id = session_id; + if (ioctl(serial_file, BDMF_CHRDEV_SESSION_CLOSE, &iop) == -1) + { + perror("close session"); + return -1; + } + session_id = -1; +#endif + return 0; +} + +static int send_to_session(char *sbuf) +{ + int rc; +#ifndef BDMF_SYSTEM_SIM + if (serial_file) + { + struct io_param iop; + /* serial communication */ + if (session_id < 0) + return print_help(0, "send: Can't send command over serial. session_id is missing\n"); + iop.session_id = session_id; + strncpy(iop.command, sbuf, sizeof(iop.command)); + rc = ioctl(serial_file, BDMF_CHRDEV_SESSION_SEND, &iop); + if (!rc) + cmd_rc = iop.rc; + } + else +#endif + { + int len = strlen(sbuf); + /* socket communication */ + if ((rc=send(client_sock, sbuf, len, 0)) != len) + rc = print_help(0, "send: failed to send command\n"); + } + return rc; +} + +static int putc_to_session(char c) +{ + int rc; +#ifndef BDMF_SYSTEM_SIM + if (serial_file) + { + /* serial communication */ + rc = write(serial_file, &c, 1); + rc = (rc == 1) ? 0 : ((rc < 0) ? rc : -EINVAL); + } + else +#endif + { + return -EOPNOTSUPP; + } + return rc; +} + + +/* Raw mode: 1960 magic shit. */ +static int terminal_set_raw_mode(void) +{ + struct termios raw; + + if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) + { + printf("tcgetattr failed. errno=%d (%s)\n", errno, strerror(errno)); + return -1; + } + + raw = orig_termios; /* modify the original mode */ + /* input modes: no break, no CR to NL, no parity check, no strip char, + * no start/stop output control. */ + raw.c_iflag &= ~(BRKINT | IGNBRK | ICRNL | INPCK | ISTRIP | IXON | IXOFF); + + /* output modes - disable post processing */ + /* raw.c_oflag &= ~(OPOST); */ + + /* control modes - set 8 bit chars */ + raw.c_cflag |= (CS8 /* | ISIG */); + + /* local modes - echoing off, canonical off, no extended functions, + * no signal chars (^Z,^C) */ + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); + /* control chars - set return condition: min number of bytes and timer. + * We want read to return every single byte, without timeout. */ + raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ + + /* put terminal in raw mode after flushing */ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0) + { + printf("tcsetattr failed. errno=%d (%s)\n", errno, strerror(errno)); + return -1; + } + + return 0; +} + +static void terminal_restore_mode(void) +{ + /* Don't even check the return value as it's too late. */ + tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); +} + + +int main(int argc, char *argv[]) +{ + /* options */ + int is_serial = 0; /* -c option */ + int is_init = 0; /* -c init */ + char *cmd = NULL; /* -cmd buffer */ + char *script_file = NULL; + int is_interactive = 0; /* -fg option */ + int is_close = 0; /* close session */ + int is_lineedit_mode = 0; /* line-edit mode. set automatically if -fg and CONFIG_LINENOISE is set */ + + char *addr; + char *cport; + int protocol = 0; + struct sockaddr_un domain_sa; + struct sockaddr_in tcp_sa; + struct sockaddr *sa = NULL; + int len = 0; + FILE *cmdf = NULL; /* script file handle */ + int i; + int rc=0; + char *pend; + char sbuf[BDMF_MAX_LINE_LENGTH] = { 0 }; + + if (argc < 2) + return print_help(1, NULL); + + /* 1st determine if it is serial or socket session */ + if (!strcmp(argv[1], "-c")) + { +#ifdef BDMF_SYSTEM_SIM + return print_help(0, "Serial connection is not supported in simulation\n"); +#endif + is_serial = 1; + /* must be followed by "init" or session_id */ + if (argc < 3) + return print_help(0, "-c must be followed by \"init\" or numerical session_id\n"); + if (!strcmp(argv[2], "init")) + is_init = 1; + else + { + session_id = strtol(argv[2], &pend, 0); + if ((argc < 4) || (session_id <= 0) || (pend && *pend)) + return print_help(1, "Invalid session_id %s after -c or too few parameters\n", argv[2]); + } + i = 3; + } + else + { + /* socket communication */ + addr = argv[1]; + if ((cport=strchr(addr, ':'))) + { + struct addrinfo hints, *res; + int rc; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; + *(cport++) = 0; /* separate address and port parts */ + rc = getaddrinfo(addr, NULL, &hints, &res); + if (rc) + { + fprintf(stderr, "Unknown host: %s\n", addr); + return -3; + } + + sa = (struct sockaddr *)&tcp_sa; + tcp_sa.sin_family = AF_INET; + tcp_sa.sin_port = htons(atoi(cport)); + protocol = AF_INET; + tcp_sa.sin_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr; + len=sizeof(struct sockaddr_in); + freeaddrinfo(res); + } + else + { + sa = (struct sockaddr *)&domain_sa; + domain_sa.sun_family = AF_UNIX; /* local is declared before socket() ^ */ + strncpy(domain_sa.sun_path, addr, sizeof(domain_sa.sun_path)); + len = strlen(domain_sa.sun_path) + sizeof(domain_sa.sun_family); + protocol = AF_UNIX; + } + i = 2; + } + /* Parse options */ + for(; i %d\n", rc); + if (!rc) + { + rc = write(serial_file, "\n", 1); + is_lineedit_mode = (rc == 1); + dprintf("write() --> %d, lineedit_mode=%d\n", rc, is_lineedit_mode); + if (!is_lineedit_mode) + { + printf("switching lineedit off. rc=%d\n", rc); + terminal_restore_mode(); + } + } + } + if (is_lineedit_mode) + { + int c = 0; + dprintf("Line-edit mode\n"); + rc = pthread_create(&cli_output_thread, NULL, bdmfmons_cli_output_thread_handler, NULL); + if (rc) + return print_help(0, "failed to create cli_output thread\n"); + while(!rx_thread_killed && (c = getchar()) >= 0) + { + /* Some terminals behave strangely. getchar() can return 0 character for no obvious reason */ + if (!c) + continue; + if (putc_to_session(c)) + goto cleanup; + } + dprintf("rx_thread_killed=%d c=%d\n", rx_thread_killed, c); + } + else + { + printf("Legacy mode. tab completion is not supported\n"); + send_to_session("\n"); /* provoke printing prompt */ + while(!rx_thread_killed && fgets(sbuf, sizeof(sbuf)-1, stdin)) + { + if (send_to_session(sbuf)) + goto cleanup; + } + } + } + else if (!is_serial) + { + char eot[2]={CHAR_EOT, 0}; + send_to_session(eot); + while(!rx_thread_killed) + ; + } + + if (is_serial && is_close) + close_serial_session(); + +cleanup: + if (is_lineedit_mode) + { + void *res; + terminal_restore_mode(); + pthread_cancel(cli_output_thread); + pthread_join(cli_output_thread, &res); + } + if (serial_file) + close(serial_file); + if (cmdf) + fclose(cmdf); + if (client_sock) + close(client_sock); + + return rc ? rc : cmd_rc; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/bs b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/bs new file mode 100755 index 00000000000..9113354cba1 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/bs @@ -0,0 +1,4 @@ +#!/bin/bash + +bdmf_shell -c `cat /var/bdmf_sh_id` -cmd $* + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/bsi b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/bsi new file mode 100755 index 00000000000..6d6f86c8a8c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/bsi @@ -0,0 +1,5 @@ +#!/bin/bash + +bdmf_shell -c `cat /var/bdmf_sh_id` -fg + + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rdpa_init.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rdpa_init.sh new file mode 100644 index 00000000000..8b07b3e2b39 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rdpa_init.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# We need to down eth0 prior to starting runner's data path init +ifconfig eth0 down &> /dev/null + +# Initialize bdmf shell +bdmf_shell -c init | while read a b ; do echo $b ; done > /var/bdmf_sh_id +alias bs="bdmf_shell -c `cat /var/bdmf_sh_id` -cmd " diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rgen30_hw_accel_dump.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rgen30_hw_accel_dump.sh new file mode 100644 index 00000000000..fe6638b4996 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rgen30_hw_accel_dump.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# +# rgen30_hw_accel_dump.sh +# + +RGEN=30 +#PLAT="DSL" + +source "/bin/runner_dump.sh" diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rgen61_hw_accel_dump.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rgen61_hw_accel_dump.sh new file mode 100644 index 00000000000..8c49e24d520 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/rgen61_hw_accel_dump.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# +# rgen61_hw_accel_dump.sh +# + +RGEN=61 +#PLAT="DSL" + +source "/bin/runner_dump.sh" diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/runner b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/runner new file mode 100644 index 00000000000..9510835f51c --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/runner @@ -0,0 +1,21 @@ +#!/bin/bash + +#LINUX_VERSION=`uname -r` +if [ "$1" = "enable" ] +then + #insmod /lib/modules/${LINUX_VERSION}/extra/pktrunner.ko + fcctl config --hw-accel 1 + + pwr config --cpuspeed on + echo "Changing power settings. Setting cpu frequency setting to adaptive." +elif [ "$1" = "disable" ] +then + #rmmod pktrunner + fcctl config --hw-accel 0 + + pwr config --cpuspeed off + echo "Changing power settings. Forcing cpu to max frequency." + echo " Set cpuspeed to on(pwr config --cpuspeed on) to make it adaptive again" +else + echo "Usage: runner enable; runner disable" +fi diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/runner_dump.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/runner_dump.sh new file mode 100644 index 00000000000..c89c6dc4dba --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/runner_dump.sh @@ -0,0 +1,292 @@ +#!/bin/sh +# +# rdp_hw_accel_dump.sh +# + +################################################### +### This script relies on RGEN and PLAT variables +################################################### + +LOOP_TIME=10 +NR_RUNS=0 +NR_REPEATS=1 +DUMP_CLEAR=0 +DUMP_DMESG=0 +DUMP_FLOW=1 +DUMP_CFG=1 +DUMP_PKTRNR=1 +MAX_PRINT="max_prints:-1" +RADIOS="0 1 2" + +show_help () { + echo "Syntax: $0 [-r repeat_count] [-t interval_time_sec] [-c] [-d] [-nfd] [-ncfg] [-npr] [-mpr]" + echo "Options:" + echo -e "\t-r repeat_count: Number of iterations driver?s data collection. Default one loop." + echo -e "\t-t interval_time_sec: Sleep time between two intervals. Default 10 sec." + echo -e "\t-c: Clear driver dumps wherever applicable. Default is not clear." + echo -e "\t-d: dmesg -c. Default no dmesg" + echo -e "\t-nfd: noflowdump. Do not dump flows." + echo -e "\t-ncfg: nocfgdump. Do not dump RDPA configuration." + echo -e "\t-npr: nopktrnrdump. Do not dump pktrunner stats." + echo -e "\t-mpr: maxprint. Provide max_prints value in decimal" + echo -e "\t-radio: Specify radio index [0-2], Default all" + exit +} + +if [ -z ${RGEN+x} ]; then echo "ERROR !! RGEN is not set"; exit 0; fi +#if [ -z ${PLAT+x} ]; then echo "ERROR !! PLAT is not set"; exit 0; fi + +# Help option +if [[ $# -eq 1 ]] && [[ $1 == "--help" ]]; then + show_help + exit 0 +fi + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -r|--repeatcount) + NR_REPEATS="$2" + shift # past argument + shift # past value + ;; + -c|--clear) + shift # past argument + DUMP_CLEAR=1 + ;; + -t|--timeinterval) + LOOP_TIME="$2" + shift # past argument + shift # past value + ;; + -d|--dmesg) + shift # past argument + DUMP_DMESG=1 + ;; + -nfd|--noflowdump) + shift # past argument + DUMP_FLOW=0 + ;; + -nm|--nomisc) + shift # past argument + DUMP_MISC=0 + ;; + -ncfg|--nocfgdump) + shift # past argument + DUMP_CFG=0 + ;; + -npr|--nopktrnrdump) + shift # past argument + DUMP_PKTRNR=0 + ;; + -mpr|--maxprint) + MAX_PRINT="max_prints:$2" + shift # past argument + shift # past value + ;; + -radio) + RADIOS="$2" + shift # past argument + shift # past value + ;; + -h|--help) + show_help + exit 0 + ;; + *) # unknown option + echo "Unknown Option $1" + show_help + exit 0; +esac +done + +if ! [ "$LOOP_TIME" -eq "$LOOP_TIME" ] 2>/dev/null; then + echo "Time interval between repeat should be number in sec." + show_help + exit 0; +fi + +if ! [ "$NR_REPEATS" -eq "$NR_REPEATS" ] 2>/dev/null; then + echo "Repeat count should be a number" + show_help + exit 0; +fi + +dump_cmd() { + echo "=================================" + echo $1 + echo "=================================" + $1 + echo -e "\n\n" +} + +rdpa_cfg_dump () { + + dump_cmd "bs /Bdmf/e system children $MAX_PRINT"; + ### +} + +rdpa_nonzero_dump () { + dump_cmd "bs /Bdmf/nZstats"; +} + +rdpa_flow_dump () { + ## Check if dump enabled + if [ $DUMP_FLOW != 1 ]; then + return + fi + + + local RDPA_INTEREST_OBJ="ucast l2_ucast mcast iptv wlan_mcast ip_class l2_class" + local RDPA_CURRENT_OBJ=`bs /Bdmf/types` + + for RDPA_EXAM_OBJ in ${RDPA_INTEREST_OBJ} + do + RDPA_OBJ=`echo " ${RDPA_CURRENT_OBJ} " | grep -m1 -o "${RDPA_EXAM_OBJ}"` + if [ "${RDPA_OBJ}" != "" ] ; then + dump_cmd "bs /Bdmf/e $RDPA_EXAM_OBJ $MAX_PRINT" + fi + done +} + +pktrnr_dump () { + ## Check if dump enabled + if [ $DUMP_PKTRNR != 1 ]; then + return + fi + + dump_cmd "cat /proc/pktrunner/accel0/stats" + #dump_cmd "cat /proc/pktrunner/accel0/flows/L2" + #dump_cmd "cat /proc/pktrunner/accel0/flows/L3" + #dump_cmd "cat /proc/pktrunner/accel0/flows/mcast" +} + +dhd_dump () { + + if [ $RGEN = 30 ] ; then + + dump_cmd "bs /Driver/rdd/pddc" + dump_cmd "bs /Driver/rdd/pdfrc" + + for RADIO_IDX in ${RADIOS} + do + dump_cmd "dhd -i wl$RADIO_IDX dump" + done + + elif [ $RGEN -gt 30 ] ; then + + dump_cmd "bs /Driver/rdd/gdfl" + + for RADIO_IDX in ${RADIOS} + do + dump_cmd "bs /Driver/rdd/pdgc $RADIO_IDX" + dump_cmd "bs /Driver/rdd/pddc $RADIO_IDX" + dump_cmd "bs /Driver/rdd/pdfrc $RADIO_IDX" + dump_cmd "dhd -i wl$RADIO_IDX dump" + done + fi +} + +wfd_dump () { + + # WFD Stats or flctl + local WFD_INTEREST_OBJ="stats flctl" + local WFD_CURRENT_OBJ=`ls /proc/wfd 2>/dev/null` + + for WFD_EXAM_OBJ in ${WFD_INTEREST_OBJ} + do + WFD_OBJ=`echo " ${WFD_CURRENT_OBJ} " | grep -m1 -o "${WFD_EXAM_OBJ}"` + if [ "${WFD_OBJ}" != "" ] ; then + dump_cmd "cat /proc/wfd/$WFD_OBJ" + fi + done + ## + + +} + +wifi_dump () { + # WFD dumps + wfd_dump + # DHD offload dumps + dhd_dump + # dump wifi data path stats + for RADIO_IDX in ${RADIOS} + do + dump_cmd "wl -i wl$RADIO_IDX dpstats" + done + ## +} + +rnr_other_dump () { + + if [ $RGEN -gt 30 ] ; then + dump_cmd "bs /Driver/qm/Print_non_empty_queues" + dump_cmd "bs /Driver/cpur sar" + dump_cmd "bs /Driver/System/Sanity" + dump_cmd "bs /Driver/Fpm/Debug_get" + dump_cmd "bs /Driver/Sbpm/Debug_get" + dump_cmd "bs /Driver/qm debug" + dump_cmd "bs /Driver/dsptchr Get flldes_bufavail" + dump_cmd "bs /Driver/dsptchr Get congestion_congstn_status" + fi + if [ $RGEN -gt 60 ] ; then + dump_cmd "bs /Driver/cnpl/bufmng" + fi + ## +} + +stats_dump () { + + ## pkt_runner dumps + pktrnr_dump + + ## nonzero rdpa dumps + rdpa_nonzero_dump + + ## Wifi dump + wifi_dump + + ## other runner dumps + rnr_other_dump + + ## flow-dump + rdpa_flow_dump + ### +} + +loop_commands () { + NR_RUNS=`expr $NR_RUNS + 1` + + if [[ $NR_REPEATS != 1 ]]; then + echo "========================================" + echo " Iteration $NR_RUNS" + echo "========================================" + fi + + ## Dump Stats/counters + stats_dump + + if [[ "$DUMP_DMESG" -eq 1 ]]; then + dmesg -c + fi + + #if [[ "$DUMP_CLEAR" -eq 1 ]]; then + # Add code here to issue command to clear counters + #fi + + if [[ $NR_REPEATS -gt $NR_RUNS ]]; then + sleep $LOOP_TIME + fi +} + +## Dump the configuration +if [[ "$DUMP_CFG" -eq 1 ]]; then + rdpa_cfg_dump +fi + +while [[ $NR_REPEATS -gt $NR_RUNS ]]; do + loop_commands +done diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/xrdp_hw_accel_dump.sh b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/xrdp_hw_accel_dump.sh new file mode 100644 index 00000000000..b8be01c2046 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bdmf_shell/scripts/xrdp_hw_accel_dump.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# +# xrdp_hw_accel_dump.sh +# + +# Starting with XRDP=RGEN40, will split later if need to differentiate within XRDP +RGEN=40 +#PLAT="DSL" + +source "/bin/runner_dump.sh" diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Bcmbuild.mk new file mode 100644 index 00000000000..d045db4fc37 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Bcmbuild.mk @@ -0,0 +1,72 @@ +EXE := blogctl +EXEALT := blog + +all dynamic install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + + +ARCH := $(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/bin +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR +# export TOOLCHAIN_PREFIX + + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin + + +ifneq ($(strip $(BUILD_FCCTL)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + (cd $(FINAL_EXE_INSTALL_DIR); ln -sf $(EXE) $(EXEALT)) + +else + +conditional_build: + @echo "Skipping $(EXE) (not configured)" + +endif + + +clean: + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Makefile new file mode 100644 index 00000000000..606fe33de7a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Makefile @@ -0,0 +1,18 @@ + +EXE := blogctl + +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin + +all: + @cp -f prebuilt/$(EXE) . + +install: all +# mkdir -p $(EXE_INSTALL_DIR) +# install -p -m 755 -t $(EXE_INSTALL_DIR) $(EXE) + mkdir -p $(INSTALLDIR)/bin + install -p -m 755 -t $(FINAL_EXE_INSTALL_DIR) $(EXE) + (cd $(FINAL_EXE_INSTALL_DIR); ln -sf $(EXE) blog) + +clean: + rm -f *.o *.d $(EXE) + rm -f $(EXE_INSTALL_DIR)/$(EXE) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Makefile.fullsrc new file mode 100644 index 00000000000..a79aac5481f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/Makefile.fullsrc @@ -0,0 +1,20 @@ +OBJS := blogctl.o blogctl_cmds.o + +LIBS := -L$(HND_SRC)/router-sysdep/blogctl_lib/ -lblogctl + +#CFLAGS += -Werror -Wfatal-errors +CFLAGS += -Wfatal-errors + +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + + +binaryonly_prepare: + -cp $(EXE) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include -Wno-stringop-truncation +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/autodetect new file mode 100644 index 00000000000..d5a218ea4a7 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/autodetect @@ -0,0 +1,5 @@ + +dependson: private/libs/blogctl +condition: ifneq ($(strip $(BUILD_BLOGCTL)),) +makeflags: $(BUILD_BLOGCTL) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/prebuilt/blogctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/prebuilt/blogctl new file mode 100755 index 00000000000..741dcb859b3 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl/prebuilt/blogctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/Makefile new file mode 100644 index 00000000000..4e90ec2a5ec --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/Makefile @@ -0,0 +1,13 @@ + +LIB = libblogctl.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/autodetect new file mode 100644 index 00000000000..e7025eb0636 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/autodetect @@ -0,0 +1,3 @@ + +condition: ifneq ($(strip $(BUILD_BLOGCTL)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/prebuilt/libblogctl.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/prebuilt/libblogctl.so new file mode 100755 index 00000000000..6479e7cdc4c Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/blogctl_lib/prebuilt/libblogctl.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/Makefile new file mode 100644 index 00000000000..6628464b5ac --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/Makefile @@ -0,0 +1,15 @@ + +EXE = bpmctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + mkdir -p $(INSTALL_DIR)/bin + (cd $(INSTALL_DIR)/bin; rm -f bpm; ln -s $(EXE) bpm) + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/Makefile.fullsrc new file mode 100644 index 00000000000..5ad7bf704df --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/Makefile.fullsrc @@ -0,0 +1,102 @@ +# +# Makefile for BPM Control Utility. +# Program Executable: bpmctl, bpm +# Set custom variables in this first section +# +EXE = bpmctl +OBJS = bpmctl.o bpmctl_cmds.o bpmctl_api.o +LIBS = + +PROGRAM_NAME_ALT:=bpm + +all dynamic install: sanity_check $(EXE) generic_exe_install + ln -sf $(EXE) $(INSTALL_DIR)/bin/$(PROGRAM_NAME_ALT) + +clean: generic_clean + rm -f $(OBJS) + rm -f $(INSTALL_DIR)/bin/$(EXE) + rm -f $(INSTALL_DIR)/bin/$(PROGRAM_NAME_ALT) + +binaryonly_dist_clean: clean generic_binaryonly_dist_clean + rm -f Makefile.fullsrc + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) + +include $(BUILD_DIR)/make.common + +# +# Command line debug feature setting +# +ifneq ($(strip $(BUILD_BPM_TRACK)),) +CFLAGS += -DBPM_TRACK +endif + +# +# Private apps and libs are allowed to include header files from the +# private and public directories. +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + + +# +# Private apps and libs are allowed to link with libraries from the +# private and public directories. +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + + +CFLAGS += -include stdint.h +# +# Not clear if this static build option is even supported anymore. +# +ifeq ($(strip $(BUILD_BPMCTL)), static) +CFLAGS += -DBUILD_STATIC +endif + +static: $(PROGRAM_NAME).a + +$(PROGRAM_NAME).a: $(PROGRAM_FILES) + $(AR) rcs $(PROGRAM_NAME).a $^ + + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/autodetect new file mode 100644 index 00000000000..ace5d05d867 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/autodetect @@ -0,0 +1,4 @@ + +condition: ifneq ($(strip $(BUILD_BPMCTL)),) +makeflags: $(BUILD_BPMCTL) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/prebuilt/bpmctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/prebuilt/bpmctl new file mode 100755 index 00000000000..4f405fb526d Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bpmctl/prebuilt/bpmctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/Makefile new file mode 100644 index 00000000000..5d690a95e20 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/Makefile @@ -0,0 +1,72 @@ + +bridge-utils: conditional_build + +.PHONY: all distclean clean conditional_build bridge-utils + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# You do not need to modify this part. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) + +include $(BUILD_DIR)/make.common + +APP=bridge-utils-1.6 +PATCH_FILE = bcm_patches/$(APP).patch + +ifneq ($(strip $(BUILD_BRCTL)),) +conditional_build: all +else +conditional_build: + @echo "skipping $(APP) (not configured)" +endif + +APPCFLAGS:=$(BRCM_COMMON_CFLAGS) +APPCFLAGS += -Wno-cpp -I$(KERNEL_LINKS_DIR) +ifneq ($(strip $(BUILD_VLAN_AGGR)),) +APPCFLAGS += -DCONFIG_BCM_VLAN_AGGREGATION -DCONFIG_BCM_KF_VLAN_AGGREGATION +endif + +$(APP)/configure: $(PATCH_FILE) $(APP).tar.gz + rm -rf $(APP) + tar xzf $(APP).tar.gz + patch -p1 -d$(APP) < $(PATCH_FILE) + (cd $(APP); autoconf -o configure) + @echo "$(APP) is untarred" + +objs/$(PROFILE_ARCH)/config_complete: $(APP)/configure + mkdir -p objs/$(PROFILE_ARCH) + (cd objs/$(PROFILE_ARCH); \ + ../../$(APP)/configure --host=$(TOOLCHAIN_PREFIX) \ + --prefix=$(BCM_FSBUILD_DIR)/gpl \ + --with-linux-headers=$(TOOLCHAIN_INCLUDE_DIR) \ + LDFLAGS=-L$(INSTALL_DIR)/lib \ + CFLAGS="$(APPCFLAGS)") + touch objs/$(PROFILE_ARCH)/config_complete + +all: objs/$(PROFILE_ARCH)/config_complete + mkdir -p $(INSTALL_DIR)/bin + $(MAKE) -C objs/$(PROFILE_ARCH) + $(MAKE) -C objs/$(PROFILE_ARCH) install + mkdir -p $(INSTALL_DIR)/bin$(BCM_INSTALL_SUFFIX_DIR) + cp -d $(BCM_FSBUILD_DIR)/gpl/sbin/brctl $(INSTALL_DIR)/bin$(BCM_INSTALL_SUFFIX_DIR) + +install: + @echo done + +clean: + rm -f $(INSTALL_DIR)/bin/brctl + rm -f $(INSTALL_DIR)/*/bin/brctl + rm -rf objs + rm -rf $(APP) + +distclean: clean + +bcm_dorel_distclean: distclean + +shell: + bash -i + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/autodetect new file mode 100644 index 00000000000..e69de29bb2d diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/bcm_patches/bridge-utils-1.6.patch b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/bcm_patches/bridge-utils-1.6.patch new file mode 100644 index 00000000000..1fcac6e5c6d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/bcm_patches/bridge-utils-1.6.patch @@ -0,0 +1,529 @@ +diff -ur bridge-utils-1.6.ori/brctl/brctl.c bridge-utils-1.6/brctl/brctl.c +--- bridge-utils-1.6.ori/brctl/brctl.c 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/brctl/brctl.c 2020-07-07 15:11:55.998638516 +0800 +@@ -70,7 +70,8 @@ + argv += optind; + if ((cmd = command_lookup(*argv)) == NULL) { + fprintf(stderr, "never heard of command [%s]\n", *argv); +- goto help; ++ /* brcm goto help; */ ++ return 1; + } + + if (argc < cmd->nargs + 1) { +diff -ur bridge-utils-1.6.ori/brctl/brctl_cmd.c bridge-utils-1.6/brctl/brctl_cmd.c +--- bridge-utils-1.6.ori/brctl/brctl_cmd.c 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/brctl/brctl_cmd.c 2020-07-07 15:11:18.458991958 +0800 +@@ -24,6 +24,13 @@ + #include + #include "libbridge.h" + #include "brctl.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include + + static int strtotimeval(struct timeval *tv, const char *time) + { +@@ -280,6 +287,281 @@ + return err != 0; + } + ++// brcm begin ++static int dump_port_mac_limits(const char *br, const char *p, void *arg) ++{ ++ int err; ++ int maxfdb; ++ int minfdb; ++ int usedfdb; ++ ++ err = br_get_port_fdb_limits(p, &maxfdb, &minfdb, &usedfdb); ++ if ( err == 0 ) ++ { ++ printf("interface max min used\n"); ++ printf("%-12s %-11d% -11d %d\n", p, maxfdb, minfdb, usedfdb); ++ } ++ return err; ++} ++ ++static int br_cmd_show_mac_lmt(int argc, char *const* argv) ++{ ++ const char *brname = argv[1]; ++ int err; ++ int maxfdb; ++ int usedfdb; ++ ++ err = br_get_fdb_limits(brname, &maxfdb, &usedfdb); ++ if ( err == 0 ) ++ { ++ printf("bridge max used\n"); ++ printf("%-12s %-11d %d\n", brname, maxfdb, usedfdb); ++ err = br_foreach_port(brname, dump_port_mac_limits, NULL); ++ } ++ return err != 0; ++} ++ ++static int br_cmd_local_switch_disable(int argc, char *const* argv) ++{ ++ int disable, err; ++ ++ if (!strcmp(argv[2], "on") || !strcmp(argv[2], "yes") ++ || !strcmp(argv[2], "1")) ++ disable = 1; ++ else if (!strcmp(argv[2], "off") || !strcmp(argv[2], "no") ++ || !strcmp(argv[2], "0")) ++ disable = 0; ++ else { ++ fprintf(stderr, "expect on/off for argument\n"); ++ return 1; ++ } ++ ++ err = br_set_local_switching_disable(argv[1], disable); ++ if (err) ++ fprintf(stderr, "set local switch disable status failed: %s\n", ++ strerror(errno)); ++ return err != 0; ++} ++ ++#define SYSFS_PATH_MAX 256 ++ ++static int get_ifindex_from_name(const char *ifname) ++{ ++ char sfspath[SYSFS_PATH_MAX]; ++ int rt; ++ FILE *fp; ++ int ifindex = 0; ++ ++ snprintf(sfspath, SYSFS_PATH_MAX, "/sys/class/net/%s/ifindex", ifname); ++ fp = fopen(sfspath, "r"); ++ if (fp != NULL) ++ { ++ rt = fscanf(fp, "%i", &ifindex); ++ fclose(fp); ++ if (rt == 1) ++ { ++ return ifindex; ++ } ++ } ++ return 0; ++} ++ ++int ll_addr_a2n(char *lladdr, int len, const char *arg) ++{ ++ int i; ++ ++ for (i=0; i 255) { ++ fprintf(stderr, "\"%s\" is invalid lladdr.\n", arg); ++ return -1; ++ } ++ lladdr[i] = temp; ++ if (!cp) ++ break; ++ arg = cp; ++ } ++ return i+1; ++} ++ ++static int br_cmd_addmacs(int argc, char *const* argv) ++{ ++ const char *brname; ++ const char *ifname; ++ const char *macaddr; ++ struct nlmsghdr *nlh; ++ struct ndmsg *ndm; ++ struct rtattr *rta; ++ char buf[NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(*ndm)) + ++ RTA_ALIGN(sizeof(*rta)) + RTA_ALIGN(ETH_ALEN)]; ++ int fd; ++ char llabuf[20]; ++ int err; ++ ++ brname = *++argv; ++ (void) brname; ++ ifname = *++argv; ++ macaddr = *++argv; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,8,0) ++ ++ memset(&buf[0], 0, sizeof(buf)); ++ nlh = (struct nlmsghdr *)&buf[0]; ++ nlh->nlmsg_len = sizeof(buf); ++ nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_REPLACE; /* create or replace */ ++ nlh->nlmsg_type = RTM_NEWNEIGH; ++ nlh->nlmsg_seq = 0; ++ ++ ndm = (struct ndmsg *)NLMSG_DATA(nlh); ++ ndm->ndm_ifindex = get_ifindex_from_name(ifname); ++ if ( 0 == ndm->ndm_ifindex ) ++ { ++ printf("get index from name returns error\n"); ++ return -1; ++ } ++ ndm->ndm_family = PF_BRIDGE; ++ ndm->ndm_flags = NTF_MASTER; ++ // add static FDB entry ++ ndm->ndm_state = NUD_NOARP; ++ ++ rta = (struct rtattr *)(NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(*ndm))); ++ rta->rta_type = NDA_LLADDR; ++ rta->rta_len = RTA_LENGTH(ETH_ALEN); ++ err = ll_addr_a2n(llabuf, sizeof(llabuf), macaddr); ++ if (err < 0) ++ printf("err in mac addr conversion\n"); ++ memcpy(RTA_DATA(rta), llabuf, ETH_ALEN); ++ ++ fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); ++ if (fd < 0) ++ { ++ printf("Cannot open netlink socket\n"); ++ return -1; ++ } ++ else ++ { ++ int status; ++ struct sockaddr_nl nladdr; ++ struct iovec iov = { ++ .iov_base = (void*)nlh, ++ .iov_len = nlh->nlmsg_len ++ }; ++ struct msghdr msg = { ++ .msg_name = &nladdr, ++ .msg_namelen = sizeof(nladdr), ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ }; ++ ++ memset(&nladdr, 0, sizeof(nladdr)); ++ nladdr.nl_family = AF_NETLINK; ++ ++ status = sendmsg(fd, &msg, 0); ++ if (status < 0) ++ { ++ printf("Cannot talk to rtnetlink"); ++ } ++ close(fd); ++ } ++#else /* LINUX_VERSION_CODE */ ++ printf ("requested API not supported in kernel version\n"); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return 0; ++} ++ ++static int br_cmd_delmacs(int argc, char *const* argv) ++{ ++ const char *brname; ++ const char *ifname; ++ const char *macaddr; ++ #if LINUX_VERSION_CODE > KERNEL_VERSION(3,8,0) ++ struct nlmsghdr *nlh; ++ struct ndmsg *ndm; ++ struct rtattr *rta; ++ char buf[NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(*ndm)) + ++ RTA_ALIGN(sizeof(*rta)) + RTA_ALIGN(ETH_ALEN)]; ++ int fd; ++ char llabuf[20]; ++ int err; ++ ++ brname = *++argv; ++ (void) brname; ++ ifname = *++argv; ++ macaddr = *++argv; ++ ++ memset(&buf[0], 0, sizeof(buf)); ++ nlh = (struct nlmsghdr *)&buf[0]; ++ nlh->nlmsg_len = sizeof(buf); ++ nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_REPLACE; /* create or replace */ ++ nlh->nlmsg_type = RTM_DELNEIGH; ++ nlh->nlmsg_seq = 0; ++ ++ ndm = (struct ndmsg *)NLMSG_DATA(nlh); ++ ndm->ndm_ifindex = get_ifindex_from_name(ifname); ++ if ( 0 == ndm->ndm_ifindex ) ++ { ++ return -1; ++ } ++ ndm->ndm_family = PF_BRIDGE; ++ ndm->ndm_flags = NTF_MASTER; ++ ++ rta = (struct rtattr *)(NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(*ndm))); ++ rta->rta_type = NDA_LLADDR; ++ rta->rta_len = RTA_LENGTH(ETH_ALEN); ++ err = ll_addr_a2n(llabuf, sizeof(llabuf), macaddr); ++ if (err < 0) ++ printf("err in mac addr conversion\n"); ++ memcpy(RTA_DATA(rta), llabuf, ETH_ALEN); ++ ++ fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); ++ if (fd < 0) ++ { ++ printf("Cannot open netlink socket\n"); ++ return -1; ++ } ++ else ++ { ++ int status; ++ struct sockaddr_nl nladdr; ++ struct iovec iov = { ++ .iov_base = (void*)nlh, ++ .iov_len = nlh->nlmsg_len ++ }; ++ struct msghdr msg = { ++ .msg_name = &nladdr, ++ .msg_namelen = sizeof(nladdr), ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ }; ++ ++ memset(&nladdr, 0, sizeof(nladdr)); ++ nladdr.nl_family = AF_NETLINK; ++ ++ status = sendmsg(fd, &msg, 0); ++ if (status < 0) ++ { ++ printf("Cannot talk to rtnetlink"); ++ } ++ close(fd); ++ } ++#else ++ printf("requested API not supported in kernel version\n"); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return 0; ++} ++// brcm end ++ + static int br_cmd_stp(int argc, char *const* argv) + { + int stp, err; +@@ -397,11 +679,17 @@ + } + + qsort(fdb, offset, sizeof(struct fdb_entry), compare_fdbs); +- ++#if defined(CONFIG_BCM_VLAN_AGGREGATION) ++ printf("port no\tvid\tmac addr\t\tis local?\tageing timer\n"); ++#else + printf("port no\tmac addr\t\tis local?\tageing timer\n"); ++#endif + for (i = 0; i < offset; i++) { + const struct fdb_entry *f = fdb + i; + printf("%3i\t", f->port_no); ++#if defined(CONFIG_BCM_VLAN_AGGREGATION) ++ printf("%4i\t", f->vid); ++#endif + printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t", + f->mac_addr[0], f->mac_addr[1], f->mac_addr[2], + f->mac_addr[3], f->mac_addr[4], f->mac_addr[5]); +@@ -479,6 +767,16 @@ + "\t\tshow bridge stp info"}, + { 2, "stp", br_cmd_stp, + " {on|off}\tturn stp on/off" }, ++// brcm begin ++ { 1, "showmaclmt", br_cmd_show_mac_lmt, ++ "\t\tshow a mac limit of bridge"}, ++ { 2, "localswitchingdisable", br_cmd_local_switch_disable, ++ " {on|off}\t\tLocal switching disable on bridge on/off"}, ++ { 3, "addmacs", br_cmd_addmacs, ++ " \t\tadd mac addresses to the bridge table"}, ++ { 3, "delmacs", br_cmd_delmacs, ++ " \t\tremove mac addresses from the bridge table"} ++// brcm end + }; + + const struct command *command_lookup(const char *cmd) +Only in bridge-utils-1.6/brctl: brctl_cmd.c.orig +diff -ur bridge-utils-1.6.ori/brctl/Makefile.in bridge-utils-1.6/brctl/Makefile.in +--- bridge-utils-1.6.ori/brctl/Makefile.in 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/brctl/Makefile.in 2020-07-07 15:11:18.458991958 +0800 +@@ -1,10 +1,12 @@ + + KERNEL_HEADERS=-I@KERNEL_HEADERS@ + ++srcdir=@srcdir@ ++ + CC=@CC@ + CFLAGS= -Wall @CFLAGS@ + LDFLAGS=@LDFLAGS@ +-INCLUDE=-I../libbridge $(KERNEL_HEADERS) ++INCLUDE=-I$(srcdir)/../libbridge -I../libbridge $(KERNEL_HEADERS) + LIBS= -L ../libbridge -lbridge @LIBS@ + + prefix=@prefix@ +@@ -36,7 +38,7 @@ + brctl: $(brctl_OBJECTS) ../libbridge/libbridge.a + $(CC) $(LDFLAGS) $(brctl_OBJECTS) $(LIBS) -o brctl + +-%.o: %.c brctl.h ++%.o: $(srcdir)/%.c $(srcdir)/brctl.h + $(CC) $(CFLAGS) $(INCLUDE) -c $< + + clean: +diff -ur bridge-utils-1.6.ori/doc/Makefile.in bridge-utils-1.6/doc/Makefile.in +--- bridge-utils-1.6.ori/doc/Makefile.in 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/doc/Makefile.in 2020-07-07 15:11:18.458991958 +0800 +@@ -15,5 +15,5 @@ + clean: + + install: +- mkdir -p $(DESTDIR)$(mandir)/man8 +- $(INSTALL) -m 644 brctl.8 $(DESTDIR)$(mandir)/man8 ++# mkdir -p $(DESTDIR)$(mandir)/man8 ++# $(INSTALL) -m 644 brctl.8 $(DESTDIR)$(mandir)/man8 +Only in bridge-utils-1.6/doc: Makefile.in.orig +diff -ur bridge-utils-1.6.ori/libbridge/libbridge_devif.c bridge-utils-1.6/libbridge/libbridge_devif.c +--- bridge-utils-1.6.ori/libbridge/libbridge_devif.c 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/libbridge/libbridge_devif.c 2020-07-07 15:11:18.458991958 +0800 +@@ -355,6 +355,11 @@ + BRCTL_SET_BRIDGE_PRIORITY); + } + ++int br_set_local_switching_disable(const char *br, int disable_state) ++{ ++ return br_set(br, "local_switching_disable", disable_state, BRCTL_GET_VERSION); ++} ++ + static int port_set(const char *bridge, const char *ifname, + const char *name, unsigned long value, + unsigned long oldcode) +@@ -404,6 +409,9 @@ + ent->port_no = f->port_no; + ent->is_local = f->is_local; + __jiffies_to_tv(&ent->ageing_timer_value, f->ageing_timer_value); ++#if defined(CONFIG_BCM_VLAN_AGGREGATION) ++ ent->vid = f->vid; ++#endif + } + + int br_read_fdb(const char *bridge, struct fdb_entry *fdbs, +@@ -447,3 +455,37 @@ + + return n; + } ++ ++int br_get_fdb_limits(const char *brname, int *maxfdb, int *usedfdb ) ++{ ++ DIR *d; ++ char path[SYSFS_PATH_MAX]; ++ ++ snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", brname); ++ d = opendir(path); ++ if (!d) ++ { ++ return -1; ++ } ++ *maxfdb = fetch_int(path, "max_fdb_entries"); ++ *usedfdb = fetch_int(path, "used_fdb_entries"); ++ return 0; ++} ++ ++int br_get_port_fdb_limits(const char *portname, int *maxfdb, int *minfdb, int *usedfdb ) ++{ ++ DIR *d; ++ char path[SYSFS_PATH_MAX]; ++ ++ snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brport", portname); ++ d = opendir(path); ++ if (!d) ++ { ++ return -1; ++ } ++ *maxfdb = fetch_int(path, "max_fdb_entries"); ++ *minfdb = fetch_int(path, "min_fdb_entries"); ++ *usedfdb = fetch_int(path, "used_fdb_entries"); ++ return 0; ++} ++ +Only in bridge-utils-1.6/libbridge: libbridge_devif.c.orig +diff -ur bridge-utils-1.6.ori/libbridge/libbridge.h bridge-utils-1.6/libbridge/libbridge.h +--- bridge-utils-1.6.ori/libbridge/libbridge.h 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/libbridge/libbridge.h 2020-07-07 15:11:18.458991958 +0800 +@@ -23,7 +23,7 @@ + #include + #include + #include +-#include ++#include + + /* defined in net/if.h but that conflicts with linux/if.h... */ + extern unsigned int if_nametoindex (const char *__ifname); +@@ -64,6 +64,9 @@ + uint16_t port_no; + unsigned char is_local; + struct timeval ageing_timer_value; ++#if defined(CONFIG_BCM_VLAN_AGGREGATION) ++ u_int16_t vid; ++#endif + }; + + struct port_info +@@ -118,4 +121,13 @@ + unsigned long skip, int num); + extern int br_set_hairpin_mode(const char *bridge, const char *dev, + int hairpin_mode); ++// brcm begin ++int br_get_fdb_limits(const char *brname, int *maxfdb, int *usedfdb ); ++int br_get_port_fdb_limits(const char *portname, int *maxfdb, int *minfdb, int *usedfdb ); ++ ++extern int br_block_stp(const char *bridge, const char *ifName); ++extern int br_mark_dedicated_stp_port(const char *bridge, ++ const char *ifName, int setting); ++extern int br_set_local_switching_disable(const char *br, int disable_state); ++// brcm end + #endif +Only in bridge-utils-1.6/libbridge: libbridge.h.orig +diff -ur bridge-utils-1.6.ori/libbridge/libbridge_private.h bridge-utils-1.6/libbridge/libbridge_private.h +--- bridge-utils-1.6.ori/libbridge/libbridge_private.h 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/libbridge/libbridge_private.h 2020-07-07 15:11:18.458991958 +0800 +@@ -24,7 +24,7 @@ + #include + #include + #include +-#include ++#include + + #define MAX_BRIDGES 1024 + #define MAX_PORTS 1024 +diff -ur bridge-utils-1.6.ori/libbridge/Makefile.in bridge-utils-1.6/libbridge/Makefile.in +--- bridge-utils-1.6.ori/libbridge/Makefile.in 2016-10-13 07:30:02.000000000 +0800 ++++ bridge-utils-1.6/libbridge/Makefile.in 2020-07-07 15:11:18.458991958 +0800 +@@ -1,11 +1,12 @@ + + KERNEL_HEADERS=-I@KERNEL_HEADERS@ ++srcdir=@srcdir@ + + AR=ar + RANLIB=@RANLIB@ + + CC=@CC@ +-CFLAGS = -Wall -g $(KERNEL_HEADERS) ++CFLAGS = -Wall -g $(KERNEL_HEADERS) @CFLAGS@ -I. + + prefix=@prefix@ + exec_prefix=@exec_prefix@ +@@ -33,9 +34,9 @@ + $(AR) rcs $@ $(libbridge_OBJECTS) + $(RANLIB) $@ + +-%.o: %.c libbridge.h libbridge_private.h ++%.o: $(srcdir)/%.c $(srcdir)/libbridge.h $(srcdir)/libbridge_private.h + $(CC) $(CFLAGS) $(INCLUDE) -c $< + +-libbridge_compat.o: libbridge_compat.c if_index.c ++libbridge_compat.o: $(srcdir)/libbridge_compat.c $(srcdir)/if_index.c + $(CC) $(CFLAGS) -c libbridge_compat.c + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/bridge-utils-1.6.tar.gz b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/bridge-utils-1.6.tar.gz new file mode 100644 index 00000000000..03d76146daa Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridge-utils/bridge-utils-1.6.tar.gz differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Bcmbuild.mk new file mode 100644 index 00000000000..b6703e8f998 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Bcmbuild.mk @@ -0,0 +1,64 @@ +LIB := libbridgeutil.so + +default: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH := $(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(KERNEL_LINKS_DIR) +ifeq ($(PROFILE_KERNEL_VER), LINUX_3_14_0) +ALLOWED_INCLUDE_PATHS +=-include bcm_local_kernel_include/linux/in6.h +endif + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + + +all install: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Makefile new file mode 100644 index 00000000000..7dd7e06f5bb --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Makefile @@ -0,0 +1,13 @@ + +LIB = libbridgeutil.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Makefile.fullsrc new file mode 100644 index 00000000000..d72470ebe4d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/Makefile.fullsrc @@ -0,0 +1,32 @@ +OBJS := bridgeutil.o + +#CFLAGS += -Werror -Wfatal-errors + +# These are public API headers needed by other apps which want to call this lib. +# Private/internal headers should not be listed here. +HEADERS := + +# from Bcmbuild.mk +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include + +all: $(LIB) + mkdir -p $(HEADER_INSTALL_DIR) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive + + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(addprefix $(HEADER_INSTALL_DIR)/,$(HEADERS)) + +binaryonly_prepare: + -cp $(LIB) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/kernel/ -I$(HND_SRC)/userspace/private/include/ +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/autodetect new file mode 100644 index 00000000000..511c0418f18 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/autodetect @@ -0,0 +1,3 @@ + +condition: ifneq ($(strip $(BUILD_BRCTL)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/prebuilt/libbridgeutil.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/prebuilt/libbridgeutil.so new file mode 100755 index 00000000000..33b4b43e1d5 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bridgeutil/prebuilt/libbridgeutil.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bshared/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bshared/Makefile new file mode 100644 index 00000000000..ba1b012fab7 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/bshared/Makefile @@ -0,0 +1,49 @@ +# +# Binary shared library Makefile for Linux router +# +# Copyright (C) 2021, Broadcom. All Rights Reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# <> +# +# $Id$ +# + +dirs = src +PREBUILTDIR = prebuilt +BSHARED = $(PREBUILTDIR)/libbshared.so + +.PHONY: all +all: + @for i in $(dirs); do \ + [ ! -d $$i ] || $(MAKE) -C $$i || exit $$? ; \ + done + +.PHONY: install +install: + install -d $(PREBUILTDIR) +# Call individual Makefiles if the directory exists which will copy to prebuilt + @for i in $(dirs); do \ + [ ! -d $$i ] || $(MAKE) -C $$i install || exit $$? ; \ + done +# Now install to router install directory from prebuilt + install -d $(INSTALLDIR)/usr/lib +# Install Binary Shared Library + install -m 755 $(BSHARED) $(INSTALLDIR)/usr/lib + +.PHONY: clean +clean: + @for i in $(dirs); do \ + [ ! -d $$i ] || $(MAKE) -C $$i clean ; \ + done diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/Makefile new file mode 100644 index 00000000000..5f6f7fda5df --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/Makefile @@ -0,0 +1,153 @@ +#*********************************************************************** +# +# Copyright (c) 2006-2007 Broadcom Corporation +# All Rights Reserved +# +#*********************************************************************** + + +# +# In most cases, you only need to modify this first section. +# +LIB = libcms_core.so + +FULL_SOURCE_OBJS = management.o phl_ene.o \ + phl.o object.o odl.o \ + locks.o remote.o phl_merge.o \ + securitylog.o \ + mdm_config.o mdm_configin.o \ + mdm_binaryHelper.o mdm_dataModelHelper.o \ + mdm_oidInfoArray.o \ + mdm_init.o \ + mdm_initdsl.o mdm_initlan.o mdm_initvpn.o \ + mdm_initstorageservice.o \ + mdm_initponwan.o mdm_initepon.o mdm_initoptical.o \ + mdm_initbmu.o \ + mdm2_init.o \ + mdm2_initqos.o \ + mdm2_initusb.o + + +OBJS = $(FULL_SOURCE_OBJS) + +all install: conditional_build + +clean: generic_oalclean generic_clean device2_clean + rm -f $(INSTALL_DIR)/lib/private/$(LIB) + + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# You do not need to modify this part. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(subst /userspace, /userspace,$(CURR_DIR)) +BUILD_DIR:=$(word 1, $(BUILD_DIR)) + +include $(BUILD_DIR)/make.common + +export BUILD_EPON_SDK_VOICE_OAM + +ifneq ($(strip $(BRCM_VOICE_SUPPORT)),) +include $(BUILD_DIR)/make.voice +endif + +ifeq ($(strip $(BUILD_CUSTOMER)),) +FULL_SOURCE_OBJS += mdm_initwlan.o +endif + +ifeq ($(BCM_PON),y) +FULL_SOURCE_OBJS += mdm_initwanfilters.o +endif + +ifneq ($(strip $(BUILD_DM_TR104_V2)),) + FULL_SOURCE_OBJS += mdm2_initvoice.o +else + FULL_SOURCE_OBJS += mdm_initvoice.o +endif + +ifneq ($(strip $(BCA_HND_EAP)),) + CFLAGS += -DBCA_HND_EAP +endif + +CFLAGS += $(SSP_TYP_COMPILER_OPTS) $(SSP_TYP_LIBS) $(SSP_LIB_INC) + + +# +# Private apps and libs are allowed to include header files from the +# private and public directories +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BCM_FSBUILD_DIR)/private/include \ + -I$(BCM_FSBUILD_DIR)/public/include \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) + +ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/public/libs/bcm_util + +ifneq ($(strip $(WIRELESS)),) +CFLAGS += -DSUPPORT_WIRELESS +ALLOWED_INCLUDE_PATHS += -I$(INC_BCMDRIVER_PATH)/include +endif + +ifeq ($(strip $(BRCM_XDSL_DISTPOINT_USE_G9991)),y) +CFLAGS += -DG9991 +endif + +ifeq ($(strip $(DISABLE_NOR_RAW_PARTITION)),y) +CFLAGS += -DDISABLE_NOR_RAW_PARTITION +endif + +#management.c needs cms_boardioctl.h, so we have to include these kernel header files +ALLOWED_INCLUDE_PATHS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(BCM_FSBUILD_DIR)/public/include + +ifeq ($(BUILD_RDPA),y) +ALLOWED_INCLUDE_PATHS += $(INC_RDP_FLAGS) +endif + +# treat all warnings as errors +CUSTOM_CFLAGS += -Werror -Wfatal-errors # NEW_FORBID_WARNINGS + + +device2: + $(MAKE) -C $(OALDIR)/device2 + +device2_clean: + $(MAKE) -C $(OALDIR)/device2 clean + + +ifneq ($(strip $(BUILD_BRCM_CMS)),) +COND_BUILD_CMS_CORE := 1 +endif +ifneq ($(strip $(BUILD_DISTRIBUTED_MDM)),) +COND_BUILD_CMS_CORE := 1 +endif + +ifeq ($(strip $(COND_BUILD_CMS_CORE)),1) + +conditional_build: generic_private_lib_install + +$(LIB): generic_oaldir $(OBJS) device2 + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) \ + $(OALDIR)/oal.a $(OALDIR)/device2/device2.a -Wl,--no-whole-archive -ldl -lpthread + + +# Generate and use dependencies. +CFLAGS += -MD +-include $(OBJS:%.o=%.d) + +else +conditional_build: + @echo "skipping $(LIB) (not configured)" +endif diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/autodetect new file mode 100644 index 00000000000..f134bcfa4d9 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/autodetect @@ -0,0 +1,2 @@ +dependson: atmctl bcmipc bcmmcast bcmssl bcmtm bdmf bridgeutil bsa dpictl eponctl eponsdk ethswctl fcctl gmacctl gponctl gponif i5api iqctl mdk private/libs/mdm_db private/libs/mdm private/libs/mdm2 private/libs/mdm2_devinfo private/libs/mdm2_dsl private/libs/mdm2_voice private/libs/mdm2_wifi private/libs/mdm2_storage private/libs/mdm2_openplat private/libs/mdm2_tr69 private/libs/mdm2_usp private/libs/mdm2_gpon private/libs/mdm2_epon private/libs/mdm2_sysmgmt private/libs/mdm_cbk_customer mocactl modsw nanoxml pwrctl rdpactl samos_telephony seltctl spdsvc spuctl tmctl private/libs/tr143_utils vlanctl wlcsm wlsysutil xdslctl ethctl public/libs/jsonc public/libs/bcm_util public/libs/cms_msg public/libs/cms_util public/libs/gen_util public/libs/bcm_flashutil public/libs/bcm_boardctl + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/linux/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/linux/Makefile new file mode 100644 index 00000000000..2aade512da1 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/linux/Makefile @@ -0,0 +1,247 @@ +#*********************************************************************** +# +# Copyright (c) 2006-2013 Broadcom Corporation +# All Rights Reserved +# +#***********************************************************************/ + +# +# In most cases, you only need to modify this first section. +# +LIB = oal.a + +REAL_OBJS = rcl_main.o rcl_lan.o rcl_system.o rcl_route.o rcl_porttriggering.o\ + rcl_virtualserver.o rcl_parentalcntrl.o rcl_qos.o rcl_pmap.o \ + rcl_cert.o rcl_pmirror.o rcl_ethswitch.o rcl_ddns.o rcl_network.o rcl_urlfilter.o \ + rcl_diag.o rcl_ipp.o rcl_dlna.o rcl_time.o rcl_ipfilter.o rcl_macfilter.o rcl_tr69c.o \ + rcl_wan.o rcl_dsl.o rcl_xtmlinkcfg.o rcl_ipsec.o rcl_lan6.o rcl_iptunnel.o \ + stl_main.o stl_diag.o stl_dlna.o stl_lan.o stl_tr69c.o \ + stl_wan.o stl_dsl.o stl_xtmlinkcfg.o \ + rcl_storageservice.o stl_storageservice.o rut_storageservice.o \ + rut_lan.o rut_system.o rut_util.o rut_ebtables.o rut_dnsproxy.o \ + rut_qosDefaultClassifications.o rut_qos.o rut_qos_class.o \ + rut_qos_queue.o rut_qos_policer.o rut_qos_ratelimit.o \ + rut_iptables.o rut_upnp.o rut_cert.o rut_ethswitch.o rut_ddns.o rut_rip.o rut_network.o \ + rut_diag.o rut_time.o rut_policyrouting.o rut_route.o \ + rut_wan.o rut_ethintf.o rut_dsl.o rut_atm.o rut_ptm.o rut_xtmlinkcfg.o rut_pppconcfg.o rut_ipconcfg.o \ + rut_wan6.o rut_ipconcfg6.o rut_pppconcfg6.o rut_lan6.o rut_iptunnel.o \ + rcl_snmp.o rut_snmp.o rut_ipsec.o rcl_pwrmngt.o rut_pwrmngt.o rut_wanlayer2.o \ + rut_pmirror.o \ + stl_bmu.o rcl_bmu.o \ + rcl_multicast.o rut_multicast.o rut_multicast6.o \ + rcl_l2tpac.o rut_l2tpac.o \ + rcl_pptpac.o rut_pptpac.o \ + rcl_ponwan.o rcl_gponwan.o rut_gponwan.o \ + rcl_eponwan.o rut_eponwan.o \ + rut_dns.o rut_dns6.o rut_wifiwan.o \ + rcl_epon.o stl_epon.o stl_selt.o rcl_selt.o \ + rut_tmctl_wrap.o \ + rcl_pmd.o stl_pmd.o \ + rcl_cwmpd.o stl_cwmpd.o \ + rcl_dad.o stl_dad.o \ + rcl_dmad.o stl_dmad.o \ + rut_dhcp.o rut_dhcp6.o \ + rcl_bbcd.o stl_bbcd.o \ + rcl_bcmmsgd.o stl_bcmmsgd.o \ + rut_json.o \ + rut_omci.o \ + oal_config.o oal_mdm.o oal_locks.o + + + +GENERATED_OBJS = build_timestamp.o + +all: $(LIB) + +clean: generic_clean + rm -f build_timestamp.c + +# +# Generate a timestamp file that is used by stl_main.c only. +# Make v3.80 does not like autogenerating .h file, so we autogenerate a .c file +# Make v3.80 on Fedora Core 3 does not like generating dependencies for the +# autogenerated .c file, so list that separately under GENERATED_OBJS +# +.FORCE: + +BUILD_TIMESTAMP := $(shell date +%y%m%d_%H%M) +BUILD_DATE_SEC := $(shell date +%s) +build_timestamp.c: .FORCE + @echo const char *build_timestamp=\"$(BUILD_TIMESTAMP)\"\; > build_timestamp.c + @echo const long build_date_sec=$(BUILD_DATE_SEC)\; >> build_timestamp.c + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# You do not need to modify this part. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(subst /userspace, /userspace,$(CURR_DIR)) +BUILD_DIR:=$(word 1, $(BUILD_DIR)) + +include $(BUILD_DIR)/make.common + +ifneq ($(strip $(BRCM_VOICE_SUPPORT)),) +include $(BUILD_DIR)/make.voice +endif + +ifeq ($(strip $(BUILD_CUSTOMER)),) +REAL_OBJS += rut_pmap.o +endif + +ifneq ($(strip $(BUILD_BRCM_UNFWLCFG)),) +REAL_OBJS += rcl_unfwireless.o stl_unfwlan.o rut_unfwlan.o +endif + +HAVESRC := $(wildcard rut_beepiptables.c) + +ifneq ($(strip $(BUILD_MODSW_EE)),) +BINARY_ONLY_OBJS = rut_beepiptables.o +else +BINARY_ONLY_OBJS = +REAL_OBJS += rut_beepstub.o +endif + + +ifeq ($(BCM_PON),y) +REAL_OBJS += rcl_ingress_filters.o stl_ingress_filters.o rut_ingress_filters.o +endif + +ifneq ($(strip $(BUILD_EPON_SDK_VOICE_OAM)),) +REAL_OBJS += stl_epon_oam.o rcl_epon_oam.o rut_epon_oam.o +endif + +ifneq ($(strip $(BUILD_TR69_PERIODIC_STATISTICS)),) +REAL_OBJS += rcl_periodicstats.o stl_periodicstats.o rut_periodicstats.o +endif + +ifneq ($(strip $(BUILD_DBUSREMOTE_TCP)),) +REAL_OBJS += rcl_dbus.o stl_dbus.o +endif + +ifneq ($(strip $(BUILD_OPENVSWITCH)),) +REAL_OBJS += rcl_openvswitch.o stl_openvswitch.o rut_openvswitch.o +endif + +ifneq ($(strip $(BRCM_PKTCBL_SUPPORT)),) +REAL_OBJS += rcl_snmpPktcbl.o stl_snmpPktcbl.o rut_snmpPktcbl.o +endif + +ifneq ($(strip $(BUILD_DM_TR104_V2)),) +REAL_OBJS += rcl2_voice.o stl2_voice.o rut2_voice.o rut_pon_voice.o +else +REAL_OBJS += rcl_voice.o stl_voice.o rut_voice.o rut_pon_voice.o +endif + +ifeq ($(BCM_PON),y) +CFLAGS += -DINIT_WAN_QUEUE_ON_LINKUP +endif + +ifneq ($(findstring _$(strip $(BRCM_CHIP))_,_63158_),) +CFLAGS += -DINIT_WAN_QUEUE_ON_LINKUP +endif + +COMBINEDOBJS = $(REAL_OBJS) $(BINARY_ONLY_OBJS) +OBJS = $(COMBINEDOBJS) $(GENERATED_OBJS) + +# +# Private apps and libs are allowed to include header files from the +# private and public directories +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I. -I..\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(BCM_FSBUILD_DIR)/public/include/json-c \ + -I$(BCM_FSBUILD_DIR)/public/include \ + -I$(BCM_FSBUILD_DIR)/private/include + +ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/public/libs/bcm_util + +ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/public/libs/bcm_flashutil + +# stl_main.c needs cms_boardioctl.h, so we need to include these kernel header files +ALLOWED_INCLUDE_PATHS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) + +ALLOWED_INCLUDE_PATHS += -I$(KERNEL_LINKS_DIR) + +ifeq ($(BUILD_RDPA),y) +ALLOWED_INCLUDE_PATHS += $(INC_RDP_FLAGS) + +ifeq ($(strip $(BUILD_RDPACTL)),y) +CFLAGS += -DSUPPORT_RDPA +endif +endif + +ifneq ($(strip $(BUILD_CUSTOMER)),) +ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/private/libs/mdm_cbk_customer/common +endif + +ifneq ($(strip $(BUILD_BRCM_UNFWLCFG)),) + ifneq ($(strip $(BUILD_CUSTOMER)),) + ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/private/libs/wlmdm_customer/src_ct + else + ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/private/libs/wlmdm/src + endif +endif + +ifeq ($(strip $(BCM_JUMBO_FRAME)),y) +CFLAGS += -DCONFIG_BCM_JUMBO_FRAME +endif + +ifeq ($(strip $(BRCM_XDSL_DISTPOINT_USE_G9991)),y) +CFLAGS += -DG9991 +endif + +CFLAGS += $(SSP_TYP_COMPILER_OPTS) +BCM_LD_FLAGS += -L$(INSTALL_DIR)/lib $(SSP_TYP_LIBS) + +ifneq ($(strip $(BUILD_SPDTEST)),) +CFLAGS += -DBRCM_SPDTEST +endif + +# treat all warnings as errors +CUSTOM_CFLAGS += -Werror -Wfatal-errors # NEW_FORBID_WARNINGS + + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# + + +# +# Generic rule makes the library oal.a +# see make.common +# +$(LIB):$(OBJS) + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +ifeq ($(strip $(HAVESRC)),) +rut_beepiptables.o: rut_beepiptables.o.$(PROFILE_ARCH).save + cat $< > $@ + +-include $(REAL_OBJS:.o=.d) + +else +-include $(COMBINEDOBJS:.o=.d) +endif + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/linux/device2/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/linux/device2/Makefile new file mode 100644 index 00000000000..3795634de96 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/cms_core/linux/device2/Makefile @@ -0,0 +1,173 @@ +#*********************************************************************** +# +# Copyright (c) 2006-2013 Broadcom Corporation +# All Rights Reserved +# +#***********************************************************************/ + +# +# In most cases, you only need to modify this first section. +# +LIB = device2.a + +REAL_OBJS := rcl2_device.o stl2_device.o \ + rcl2_ip.o stl2_ip.o rut2_ip.o rut2_ip6.o \ + rut2_ipservicecfg.o rut2_ipservicecfg6.o \ + rcl2_bridging.o stl2_bridging.o rut2_bridging.o \ + rcl2_ppp.o stl2_ppp.o rut2_ppp.o \ + rcl2_interfacestack.o stl2_interfacestack.o \ + rut2_lan.o rcl2_hosts.o stl2_hosts.o \ + rcl2_ethernet.o stl2_ethernet.o rut2_ethernet.o \ + rcl2_ethernetlink.o stl2_ethernetlink.o \ + rcl2_ethernetvlantermination.o stl2_ethernetvlantermination.o rut2_ethernetvlantermination.o \ + rut2_nat.o \ + rcl2_dhcpv4.o stl2_dhcpv4.o rut2_dhcpv4.o \ + rcl2_qos.o stl2_qos.o rut2_qos_queue_stats.o \ + rut2_qos_class.o rut2_qos_queue.o rut2_qos_policer.o \ + rcl2_route.o stl2_route.o rut2_route.o rut2_route6.o \ + rcl2_neighbordiscovery.o stl2_neighbordiscovery.o rut2_neighbordiscovery.o \ + rcl2_routeradvertisement.o stl2_routeradvertisement.o \ + rcl2_lanConfigSecurity.o stl2_lanConfigSecurity.o \ + rcl2_dns.o stl2_dns.o rut2_dns.o rut2_dns6.o \ + rcl2_dslite.o stl2_dslite.o \ + rcl2_ipv6rd.o stl2_ipv6rd.o rut2_iptunnel.o\ + rcl2_dhcpv6.o stl2_dhcpv6.o rcl2_dhcpv6client.o stl2_dhcpv6client.o rcl2_dhcpv6server.o stl2_dhcpv6server.o\ + rut2_dhcpv6.o \ + rut2_util.o \ + rcl2_cert.o stl2_cert.o rut2_cert.o \ + rut2_wan.o rut2_wan6.o \ + rcl2_nat.o stl2_nat.o \ + rut2_iptables.o \ + rcl2_firewall.o stl2_firewall.o \ + rut2_multicast.o \ + rut2_firmware.o \ + rut2_routeradvertisement.o \ + rcl2_gatewayInfo.o stl2_gatewayInfo.o \ + rcl2_macfilter.o stl2_macfilter.o \ + rcl2_ipsec.o stl2_ipsec.o rut2_ipsec.o \ + rcl2_ethlag.o rut2_ethlag.o stl2_ethlag.o + + +GENERATED_OBJS := + +all: $(LIB) + +clean: generic_clean + + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# You do not need to modify this part. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(subst /userspace, /userspace,$(CURR_DIR)) +BUILD_DIR:=$(word 1, $(BUILD_DIR)) + +include $(BUILD_DIR)/make.common + +ifneq ($(strip $(BRCM_VOICE_SUPPORT)),) +include $(BUILD_DIR)/make.voice +endif + + +ifneq ($(strip $(BUILD_MAP)),) +REAL_OBJS += rcl2_map.o stl2_map.o +endif + +ifneq ($(strip $(BUILD_GPON))$(strip $(BUILD_EPON_SDK)),) +REAL_OBJS += rcl2_optical.o stl2_optical.o +endif + +ifneq ($(strip $(BUILD_IEEE1905)),) +REAL_OBJS += rcl2_ieee1905.o stl2_ieee1905.o rut2_ieee1905.o +endif + +ifneq ($(strip $(BUILD_ZEBRA)),) +REAL_OBJS += rut2_rip.o +endif + +ifneq ($(strip $(BUILD_BUSYBOX_NTPD))$(strip $(BUILD_BRCM_BDK)),) +REAL_OBJS += rcl2_time.o stl2_time.o rut2_time.o +endif + +ifneq ($(strip $(BRCM_DRIVER_USB)),) +REAL_OBJS += rcl2_usb.o stl2_usb.o +endif + +ifneq ($(strip $(BUILD_L2TPAC)),) +REAL_OBJS += rcl2_l2tpac.o stl2_l2tpac.o rut2_l2tpac.o +endif + +ifneq ($(strip $(BUILD_ACCEL_PPTP)),) +REAL_OBJS += rcl2_pptpac.o stl2_pptpac.o rut2_pptpac.o +endif + +OBJS = $(REAL_OBJS) $(GENERATED_OBJS) + +# +# Private apps and libs are allowed to include header files from the +# private and public directories +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I. -I.. -I../.. \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(BCM_FSBUILD_DIR)/public/include \ + -I$(BCM_FSBUILD_DIR)/private/include + + +ALLOWED_INCLUDE_PATHS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) + +ALLOWED_INCLUDE_PATHS += -I$(KERNEL_LINKS_DIR) + +ifeq ($(BUILD_RDPACTL),y) +ALLOWED_INCLUDE_PATHS += $(INC_RDP_FLAGS) +endif + +ifeq ($(strip $(BUILD_IEEE1905)),y) +ALLOWED_INCLUDE_PATHS += -I$(BUILD_DIR)/userspace/private/apps/ieee1905 +endif + + +# treat all warnings as errors +# CUSTOM_CFLAGS += -Werror -Wfatal-errors # NEW_FORBID_WARNINGS + + +ifeq ($(strip $(BUILD_RDPACTL)),y) +CFLAGS += -DSUPPORT_RDPA +endif + +CFLAGS += $(SSP_TYP_COMPILER_OPTS) +BCM_LD_FLAGS += -L$(INSTALL_DIR)/lib $(SSP_TYP_LIBS) + + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# + + +$(LIB): $(OBJS) + $(AR) -rcs $@ $(OBJS) + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +-include $(REAL_OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/common.mak b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/common.mak new file mode 120000 index 00000000000..dd6379e3039 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/common.mak @@ -0,0 +1 @@ +../../src/router/common.mak \ No newline at end of file diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/Makefile new file mode 100644 index 00000000000..77f86e58a29 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/Makefile @@ -0,0 +1,62 @@ +# +# Router dhd_monitor Makefile +# +# Copyright (C) 2022, Broadcom. All Rights Reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# +# <> +# +# + +include $(TOP)/.config + +CFLAGS += -I. -I$(TOP)/shared -I$(SRCBASE)/include -I$(SRCBASE)/../components/shared -I$(SRCBASE)/../components/wlioctl/include -I$(SRCBASE)/../components/proto/include -I$(SRCBASE)/common/include + +ifeq ($(strip $(BCA_HNDROUTER)),) +CFLAGS += -I$(TOP)/busybox-1.x +endif + +# LDFLAGS += -L$(TOP)/nvram -L$(PLATFORMDIR)/install/nvram/usr/lib -lnvram +# LDFLAGS += -L$(TOP)/shared -L$(PLATFORMDIR)/install/shared/usr/lib -lshared -lpthread +LDFLAGS += -L$(TOP_PLATFORM)/wlcsm -lwlcsm +LDFLAGS += -L$(TOP_PLATFORM)/nvram -L$(PLATFORMDIR)/install/nvram/usr/lib -lnvram -lpthread +LDFLAGS += -L$(TOP)/shared -L$(PLATFORMDIR)/install/shared/usr/lib -lshared +LDFLAGS += $(EXTRA_LDFLAGS) + +OBJS := dhd_monitor.o + +all: debug_monitor + +clean: + rm -f *.o dhd_monitor .*.depend + +install: all + install -d $(INSTALLDIR)/usr/sbin + install debug_monitor $(INSTALLDIR)/usr/sbin + $(STRIP) $(INSTALLDIR)/usr/sbin/debug_monitor + +ifneq ($(PREBUILT_BCMBIN),1) +debug_monitor: $(OBJS) + $(CC) -o $@ $(OBJS) $(LDFLAGS) +else +debug_monitor: + cp -f $(TOP_PLATFORM)/$(shell pwd | sed 's/\(.*router-sysdep\/\)//')/$(PRBM_DIR)/$@ ./ +endif + +%.o: .%.depend +.%.depend: %.c + $(CC) $(CFLAGS) -M $< > $@ + +-include $(OBJS:%.o=.%.depend) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/dhd_monitor.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/dhd_monitor.c new file mode 100644 index 00000000000..ad79779f208 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/dhd_monitor.c @@ -0,0 +1,896 @@ +/* + * DHD Monitor Daemon + * + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: dhd_monitor.c 793019 2020-11-10 22:07:19Z $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef BCA_HNDROUTER +#include /* for uname */ +#endif /* BCA_HNDROUTER */ +#include + +#include + +/* defines */ +#ifndef RAMFS_MAGIC +#define RAMFS_MAGIC 0x858458f6 +#endif + +#ifndef TMPFS_MAGIC +#define TMPFS_MAGIC 0x01021994 +#endif + +#define LOG_BASE_PATH "/tmp/crash_logs" +#define CRASH_LOG_PREFIX "debug-" +#define LOG_UNAME_FILENAME "uname.txt" +#define LOG_DMESG_FILENAME "dmesg.txt" +#define LOG_DONGLE_MEM_FILENAME "dongle_mem_dump.bin" +#define IF_IDX_FILE_PATH "/tmp/failed_if.txt" +#define LOG_D11REGDUMP_FILENAME "d11reg_dump.txt" +#define LOG_D11REGXDUMP_FILENAME "d11regx_dump.txt" +#define LOG_CONSOLE_DUMP "console_dump.txt" +#define LOG_SOCRAM_DUMP "socram_dump.txt" +#define LOG_SCTPLDUMP_FILENAME "sctpl_dump.txt" +#define LOG_SCTPLXDUMP_FILENAME "sctplx_dump.txt" +#define LOG_VASIPDUMP_FILENAME "vasip_dump.txt" +#define DEBUG_MONITOR_FILENAME "/tmp/debug_monitor.txt" + +//#if defined(BCA_CPEROUTER) +#if 0 +#define rc_stop() /* do nothing */ +#define rc_start() system("nvram restart") +#define rc_restart() system("nvram restart") +#define rc_reboot() system("reboot") + +#define unload_driver(nic) (nic) ? \ + system("/etc/init.d/bcm-wlan-drivers.sh stop wl") : \ + system("/etc/init.d/bcm-wlan-drivers.sh stop dhd") +#define load_driver(nic) (nic) ? \ + system("/etc/init.d/bcm-wlan-drivers.sh start wl") : \ + system("/etc/init.d/bcm-wlan-drivers.sh start dhd") + +#elif defined(BCA_HNDROUTER) + +#define rc_stop() kill(1, SIGINT) +#define rc_start() kill(1, SIGUSR2) +#define rc_restart() kill(1, SIGHUP) +#define rc_reboot() kill(1, SIGTERM) + +#define unload_driver(nic) eval("rmmod", (nic ? "wl" : "dhd")) +#define load_driver(nic) { \ + struct utsname name; \ + char buf[PATH_MAX]; \ + uname(&name); \ + snprintf(buf, sizeof(buf), \ + (nic ? "/lib/modules/%s/extra/wl.ko" : "/lib/modules/%s/extra/dhd.ko"), \ + name.release); \ + eval("insmod", buf, (!nic && nvram_match("build_name", "RT-AXE7800")) ? "instance_base=1 dhd_msg_level=0" : "dhd_msg_level=0"); \ +} + + +#else /* ! BCA_HNDROUTER && !BCA_CPEROUTER */ + +#define rc_stop() kill(1, SIGINT) +#define rc_start() kill(1, SIGUSR2) +#define rc_restart() kill(1, SIGHUP) +#define rc_reboot() kill(1, SIGTERM) + +#define unload_driver(nic) eval("rmmod", (nic ? "wl" : "dhd")) +#define load_driver(nic) eval("insmod", (nic ? "/tmp/wl.ko" : "/tmp/dhd.ko")) +#endif /* !BCA_CPEROUTER && !BCA_HNDROUTER */ + +/* Number of crash logs to retain */ +#define MAX_CRASH_LOGS 3 + +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + +#define DM_BUF_SZ 256 +#define DM_DIR "/tmp/dm" +#define DM_DEPENDENCY_DEPTH_MAX 6 // recurse up to DM_DEPENDENCY_DEPTH_MAX +#define DM_INTERVAL 5 /* call debug monitor at every 5th tick only */ + +int dhd_monitor_msglevel = 0; + +/* Debug Print */ +#define DHD_MONITOR_ERROR 0x000001 +#define DHD_MONITOR_SYSLOG 0x000004 + +#define dprintf(fmt, arg...) \ + do { \ + if (dhd_monitor_msglevel & DHD_MONITOR_ERROR) \ + fprintf(stderr, fmt, ##arg); \ + if (dhd_monitor_msglevel & DHD_MONITOR_SYSLOG) \ + logmessage("dhd_monitor", "%s(%d): "fmt, __FUNCTION__, __LINE__, ##arg); \ + } while (0) + +#define printf2(fmt, arg...) \ + do { \ + printf(fmt, ##arg); \ + if (dhd_monitor_msglevel & DHD_MONITOR_SYSLOG) \ + logmessage("dhd_monitor", "%s(%d): "fmt, __FUNCTION__, __LINE__, ##arg); \ + } while (0) + +static int dm_is_process_active(char * dirname); +static void dm_trim(char *str, size_t sz); +static int dm_read_pid_info_file(char *path, char *dep_cmd, size_t dep_cmd_sz, + char *process_cmd, size_t process_cmd_sz); +static int dm_handle_process(char *pid, unsigned int depth); +static unsigned char dm_match_cmd(char *pid, char *process_cmd_needle); +static unsigned char dm_get_pid_of_cmd(char *dep_cmd, char *dep_pid, size_t dep_pid_sz); +static void dm_watchdog(); + +char *_mod_name = NULL; +int dbg_mon_disab_rstrt = FALSE; +//#if defined(__CONFIG_DHDAP__) +#if 1 +char *_backup_dir = NULL; + +static int do_command(const char *cmd) +{ + int status = system(cmd); +#ifdef WIFEXITED + if (!WIFEXITED(status)) { + dprintf("%s: command (\"%s\") terminated\n", + _mod_name, cmd); + return -1; + } + + status = WEXITSTATUS(status); +#endif + if (status) { + dprintf("%s: command (\"%s\") failed: %s\n", _mod_name, + cmd, strerror(status)); + return -1; + } + return 0; +} + +static void get_timestamp(char *buffer, int max_len) +{ + time_t rawtime; + struct tm *info; + + time(&rawtime); + info = localtime(&rawtime); + strftime(buffer, max_len, "%F_%T", info); + return; +} + +static void handle_recovery(int nic_wl) +{ + char *val = (char *) nvram_get("fast_restart"); + + if (val && atoi(val)) { + /* Fast Restart - rc_restart */ + /* stop all services */ + printf2("%s: stop services\n", _mod_name); +// rc_stop(); + + /* rc_stop is a non-blocking call. So, add sufficient sleep + * to make sure all services are stopped before proceeding. + */ + sleep(3); + + /* unload dhd */ + printf2("%s: unload dhd\n", _mod_name); + unload_driver(nic_wl); + sleep(1); + + /* reload dhd */ + printf2("%s: reload dhd\n", _mod_name); + load_driver(nic_wl); + sleep(1); + + /* start all services */ + printf2("%s: restart services\n", _mod_name); +// rc_start(); + sleep(1); + system("restart_wireless"); + } else { + /* Full restart - reboot */ + val = (char *) nvram_get("watchdog"); + if (val && atoi(val)) { + /* full reboot */ + printf2("%s: rebooting system watchdog=%d \n", _mod_name, val?atoi(val):0); + rc_reboot(); + } else { + printf2("%s: watchdog disabled, ignoring dongle trap/wl kernel panic\n", + _mod_name); + } + } +} + +/* Filter out none "*.tgz" files */ +static int dir_filter(const struct dirent *dptr) +{ + if (strstr(dptr->d_name, CRASH_LOG_PREFIX) && strstr(dptr->d_name, ".tgz")) + return 1; + return 0; +} + +/* Remove any extra crash logs that might have accumulated over time */ +/* Prune the oldest crash logs */ +/* retains: Number of crash logs to retain */ +static int delete_extra_crash_files(const char *log_dir, uint retains) +{ + struct dirent **fnamelist; + int n, i; + char filepath[256]; + + if (!log_dir) { + dprintf("%s: Error: log_dir is NULL\n", _mod_name); + return -1; + } + + n = scandir(log_dir, &fnamelist, dir_filter, alphasort); + if (n < 0) { + dprintf("%s: could not scan log_dir(%s) folder, error: %s\n", _mod_name, + log_dir, strerror(errno)); + } else { + int deletes = n - retains; + for (i = 0; i < n; i++) { + if (deletes > 0) { + deletes--; + printf2("%s: pruning old crash log - %s/%s\n", _mod_name, + log_dir, fnamelist[i]->d_name); + snprintf(filepath, sizeof(filepath), "%s/%s", + log_dir, fnamelist[i]->d_name); + unlink(filepath); + } + /* free each entry allocated by scandir() */ + free(fnamelist[i]); + } + free(fnamelist); + } + + return 0; +} + +static int get_sys_free_mem(void) +{ + FILE *fp; + char buf[PATH_MAX]; + int free_mem = -1; + + if ((fp = fopen("/proc/meminfo", "r")) == NULL) { + dprintf("%s: read meminfo fail, %s\n", _mod_name, strerror(errno)); + return -1; + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (sscanf(buf, "MemFree: %d kB", &free_mem)) + break; + } + fclose(fp); + + return free_mem; +} + +static int get_dir_free_space(const char *dir) +{ + struct statfs dir_statfs; + int free_space = 0; + + if (statfs(dir, &dir_statfs)) { + dprintf("%s: statfs backup dir %s fail, error: %s\n", _mod_name, dir, + strerror(errno)); + return -1; + } + + if (dir_statfs.f_type == RAMFS_MAGIC || + dir_statfs.f_type == TMPFS_MAGIC) { + if ((free_space = get_sys_free_mem()) < 0) { + dprintf("%s: get sys free mem fail\n", _mod_name); + return -1; + } + free_space = free_space * 1024; + } else { + free_space = dir_statfs.f_bsize * dir_statfs.f_bfree; + } + + return free_space; +} + +static int is_ramfs(const char *dir) +{ + struct statfs dir_statfs; + int ret = 0; + + if (statfs(dir, &dir_statfs)) { + dprintf("%s: statfs backup dir %s fail, error: %s\n", _mod_name, dir, + strerror(errno)); + return ret; + } + + if (dir_statfs.f_type == RAMFS_MAGIC || + dir_statfs.f_type == TMPFS_MAGIC) { + ret = 1; + } + + return ret; +} + +static int backup_logs(char *timestamp, const char *backup_dir) +{ + char logfile[128]; + char cp_file[256]; + DIR *dir; + struct stat log_stat; + int free_space = 0; + int ret = -1; + + if (!timestamp) { + dprintf("%s: Error: timestamp is NULL\n", _mod_name); + goto fail; + } + + if (!backup_dir) { + dprintf("%s: Error: backup_dir is NULL\n", _mod_name); + goto fail; + } + + if (!(dir = opendir(backup_dir))) { + dprintf("%s: open backup dir %s fail, %s\n", _mod_name, backup_dir, + strerror(errno)); + goto fail; + } + closedir(dir); + + if (access(backup_dir, W_OK)) { + dprintf("%s: access backup dir %s fail, error: %s\n", _mod_name, backup_dir, + strerror(errno)); + goto fail; + } + + snprintf(logfile, sizeof(logfile), "%s/%s%s.tgz", LOG_BASE_PATH, + CRASH_LOG_PREFIX, timestamp); + + if (stat(logfile, &log_stat)) { + dprintf("%s: open log file %s fail, %s\n", _mod_name, logfile, + strerror(errno)); + goto fail; + } + + free_space = get_dir_free_space(backup_dir); + + if (log_stat.st_size > free_space || log_stat.st_size == 0) { + dprintf("%s: log size (%d) over backup dir (%s%s)" + " available space (%d)\n", _mod_name, log_stat.st_size, + backup_dir, is_ramfs(backup_dir)? " a ram based fs": "", free_space); + goto fail; + } + + snprintf(cp_file, sizeof(cp_file), "cp %s %s", logfile, backup_dir); + ret = do_command(cp_file); + if (ret < 0) { + dprintf("%s: failed to backup logfile %s\n", _mod_name, + logfile); + goto fail; + } + + printf2("%s: logfile (%s) are backed up to (%s%s)\n", + _mod_name, logfile, backup_dir, + is_ramfs(backup_dir)? " a ram based fs": ""); + + snprintf(cp_file, sizeof(cp_file), "rm -rf %s", LOG_BASE_PATH); + ret = do_command(cp_file); + if (ret < 0) + dprintf("%s: failed to delete temp folder %s\n", _mod_name, LOG_BASE_PATH); + + sync(); + fflush(stdout); + return 0; + +fail: + snprintf(cp_file, sizeof(cp_file), "rm -rf %s", LOG_BASE_PATH); + ret = do_command(cp_file); + if (ret < 0) + dprintf("%s: failed to delete temp folder %s\n", _mod_name, LOG_BASE_PATH); + + fflush(stderr); + return ret; +} + +static int capture_logs(int noclk, char *timestamp, int nic_wl) +{ + char basepath[128]; + char filepath[256]; + char command[256]; + struct stat file_stat; + FILE *fp; + char if_name[16]; + int ch, nch; + int error = 0; + int ret = -1; + int skip_dumps = 0; + + /* create the output directory for the logs */ + snprintf(basepath, sizeof(basepath), "%s/%s%s", LOG_BASE_PATH, + CRASH_LOG_PREFIX, timestamp); + if (mkdir(LOG_BASE_PATH, 0777) < 0 && errno != EEXIST) { + perror("could not create dhd log folder"); + printf2("%s: could not create %s folder\n", _mod_name, LOG_BASE_PATH); + return ret; + } + if (mkdir(basepath, 0777) < 0 && errno != EEXIST) { + perror("could not create dhd log folder"); + printf2("%s: could not create %s folder\n", _mod_name, basepath); + return ret; + } + + /* dump version */ + snprintf(command, sizeof(command), "uname -a > %s/%s", basepath, LOG_UNAME_FILENAME); + do_command(command); + + /* copy the dongle mem dump if available */ + if (stat("/tmp/mem_dump", &file_stat) == 0) { + snprintf(command, sizeof(command), "cp /tmp/mem_dump %s/%s", basepath, LOG_DONGLE_MEM_FILENAME); + do_command(command); + do_command("rm -f /tmp/mem_dump"); + /* only skip dumps when noclk is set */ + skip_dumps = noclk; + } else { + printf2("%s: dongle memory dump is not available\n", _mod_name); + } + + /* copy the macreg dump files if available */ + snprintf(filepath, sizeof(filepath), "%s/", basepath); + snprintf(command, sizeof(command), "ls /tmp/dump_*.txt"); + if (!do_command(command)) { + snprintf(command, sizeof(command), "cp /tmp/dump_*.txt %s", filepath); + do_command(command); + snprintf(command, sizeof(command), "rm -f /tmp/dump_*.txt"); + do_command(command); + } + + /* dump dmesg to command */ + snprintf(command, sizeof(command), "dmesg -c > %s/%s", basepath, LOG_DMESG_FILENAME); + do_command(command); + + if (nic_wl) { + goto exit; + } + + /* Get the interface name */ + fp = fopen(IF_IDX_FILE_PATH, "r"); + if (!fp) { + printf2("%s: cannot open file %s\n", _mod_name, IF_IDX_FILE_PATH); + error = -1; + goto exit; + } else { + // get failed interface name + nch = 0; + while ((ch = fgetc(fp)) != '\n' && ch != ' ' && ch != EOF) { + if_name[nch++] = ch; + } + if_name[nch] = '\0'; + fclose(fp); + } + + printf2("%s: Trap/Assert on interface %s!! noclk %d\n", + _mod_name, if_name, noclk); + + if (skip_dumps) + goto exit; + + /* dump console log */ + snprintf(command, sizeof(command), "dhd -i %s consoledump > %s/%s", + if_name, basepath, LOG_CONSOLE_DUMP); + do_command(command); + + /* SOCRAM dump to socram_dump.txt */ + snprintf(command, sizeof(command), "dhd -i %s upload %s/%s", + if_name, basepath, LOG_SOCRAM_DUMP); + do_command(command); + + if (noclk) { + goto exit; + } + + /* dump d11reg to command */ + snprintf(command, sizeof(command), "echo \"%s dump\" > %s/%s", + if_name, basepath, LOG_D11REGDUMP_FILENAME); + do_command(command); + + /* Make sure dongle is dead */ + snprintf(command, sizeof(command), "dhd -i %s pcie_device_trap >> %s/%s", + if_name, basepath, LOG_D11REGDUMP_FILENAME); + do_command(command); + + /* dump PSMr regs */ + snprintf(command, sizeof(command), "dhd -i %s dump_mac > %s/%s", + if_name, basepath, LOG_D11REGDUMP_FILENAME); + do_command(command); + + /* dump PSMx regs */ + snprintf(command, sizeof(command), "dhd -i %s dump_mac -x > %s/%s", + if_name, basepath, LOG_D11REGXDUMP_FILENAME); + do_command(command); + + /* dump sample capture log */ + snprintf(command, sizeof(command), "dhd -i %s dump_sctpl > %s/%s", + if_name, basepath, LOG_SCTPLDUMP_FILENAME); + do_command(command); + + /* dump SHMx sample capture log */ + snprintf(command, sizeof(command), "dhd -i %s dump_sctpl -u shmx > %s/%s", + if_name, basepath, LOG_SCTPLXDUMP_FILENAME); + do_command(command); + + /* dump vasip dump log */ + snprintf(command, sizeof(command), "dhd -i %s dump_svmp > %s/%s", + if_name, basepath, LOG_VASIPDUMP_FILENAME); + do_command(command); + +exit: + /* assure file handles are idle before creating tar */ + sync(); + + /* tar/zip the logs and memory dump */ + snprintf(command, sizeof(command), "tar cf %s.tar %s%s -C %s", basepath, + CRASH_LOG_PREFIX, timestamp, LOG_BASE_PATH); + if (do_command(command) < 0) + return -1; + + /* delete the raw folder */ + snprintf(command, sizeof(command), "rm -rf %s", basepath); + do_command(command); + + snprintf(command, sizeof(command), "gzip -c %s.tar > %s.tgz", basepath, + basepath); + if (do_command(command) < 0) + return -1; + + snprintf(filepath, sizeof(filepath), "%s.tgz", basepath); + if ((stat(filepath, &file_stat) == 0) && file_stat.st_size) { + printf2("%s: log (%s) is collected, file size %d\n", _mod_name, + filepath, file_stat.st_size); + ret = file_stat.st_size; + } else { + printf2("%s: log (%s) is not available or an empty file\n", _mod_name, filepath); + } + + return ret; +} + +static void sig_handler(int signo) +{ + char timestamp[64], *tmp; + int nic_wl = 1; + int log_size; + int retain_logs; + int free_space = 0; + + printf2("%s: Detected firmware trap/assert !!\n", _mod_name); + + /* figure out module type. dhd or nic */ +#if 0 + char *val = (char *) nvram_get("kernel_mods"); + + if (val && !strstr(val, "dhd")) { + nic_wl = 1; + } + printf2("%s: kernel_mods: %s nic_wl %d\n", + _mod_name, (val ? val : "unset"), nic_wl); +#else + char wl_ifnames[64] = { 0 }; + char word[64]={0}, *next = NULL; + strlcpy(wl_ifnames, nvram_safe_get("wl_ifnames"), sizeof(wl_ifnames)); + foreach (word, wl_ifnames, next) { + if (!dhd_probe(word)) { + nic_wl = 0; + break; + } + } +#endif + + /* get current timestamp */ + get_timestamp(timestamp, sizeof(timestamp)); + /* reformatting time stamp string */ + tmp = timestamp; + while (*tmp) { + if (*tmp == '-' || *tmp == ':') { + *tmp = '_'; + } + tmp++; + } + printf2("%s: Logging timestamp: %s\n", _mod_name, timestamp); + + /* retain latest crash logs under /tmp/crash_logs */ + delete_extra_crash_files(LOG_BASE_PATH, (MAX_CRASH_LOGS - 1)); + + /* capture all relevant logs */ + log_size = capture_logs((signo == SIGUSR2 ? 1 : 0), timestamp, nic_wl); + if (log_size < 0) { + printf2("%s: capture failed\n", _mod_name); + return; + } + + for (retain_logs = (MAX_CRASH_LOGS - 1); retain_logs >= 0; retain_logs--) { + printf2("%s: going to retain %d log(s) under backup dir (%s)\n", + _mod_name, retain_logs, _backup_dir); + delete_extra_crash_files(_backup_dir, retain_logs); + + if (retain_logs) { + free_space = get_dir_free_space(_backup_dir); + if (free_space < 0) { + /* failed to get disk space of backup dir, skip space check */ + break; + } + + if (log_size > free_space) { + printf2("%s: Disk space (%d) not enough for new log (%d), " + "retain one less log\n", + _mod_name, free_space, log_size); + } else { + /* free disk space is large enough for the new log */ + break; + } + } + } + + /* back up the logs to persistent store */ + if (!nic_wl) + backup_logs(timestamp, _backup_dir); + + /* flush file system operations */ + sync(); + + /* reboot or rc_restart based on configuration */ + handle_recovery(nic_wl); +} + +void usage(char *progname) +{ + printf("Usage: %s \n", progname); +} +#endif /* __CONFIG_DHDAP__ */ + +static int dm_is_process_active(char * pid) +{ + char proc_path[DM_BUF_SZ]; + DIR *dir; + + snprintf(proc_path, sizeof(proc_path), "/proc/%s", pid); + + if ((dir = opendir(proc_path)) == NULL) { + dprintf("%s error opening %s\n", __FUNCTION__, proc_path); + return FALSE; + } + + closedir(dir); + return TRUE; +} + +/* trim trailing space like characters */ +static void dm_trim(char *str, size_t sz) +{ + size_t len = 0; + int i; + + if (!str || !str[0]) { + return; + } + + len = strnlen(str, sz); + + for (i = len - 1; i > 0 && isspace(str[i]); i--) { + str[i] = '\0'; + } +} + +static int dm_read_pid_info_file(char *path, char *dep_cmd, size_t dep_cmd_sz, + char *process_cmd, size_t process_cmd_sz) +{ + FILE *fp; + + if ((fp = fopen(path, "r")) == 0) { + return -1; + } + + fgets(dep_cmd, dep_cmd_sz, fp); + dm_trim(dep_cmd, dep_cmd_sz); + + fgets(process_cmd, process_cmd_sz, fp); + dm_trim(process_cmd, process_cmd_sz); + + fclose(fp); + + return 0; +} + +static int dm_handle_process(char *pid, unsigned int depth) +{ + char process_dm_path[DM_BUF_SZ]; + char dep_cmd[DM_BUF_SZ] = {0}; + char process_cmd[DM_BUF_SZ] = {0}; + char dep_pid[DM_BUF_SZ] = {0}; + + if (depth > DM_DEPENDENCY_DEPTH_MAX) { + return -1; + } + + if (nvram_match("wlready", "0")) + return FALSE; + + if (dm_is_process_active(pid)) { + // TODO: could check timestamp if agreed to touch DM_DIR + // at specific intervals + // if process is active; nothing to do + return FALSE; + } + + printf2("%s process id %s does not exist will restart\n", + __FUNCTION__, pid); + + snprintf(process_dm_path, sizeof(process_dm_path), "%s/%s", DM_DIR, pid); + + // if process is not active + if (dm_read_pid_info_file(process_dm_path, dep_cmd, sizeof(dep_cmd), + process_cmd, sizeof(process_cmd)) != 0) { + return FALSE; + } + + // if dependency is mentioned ... + if (dep_cmd[0] && dep_cmd[0] != '\r' && dep_cmd[0] != '\n') { + // ... find the pid of the dep_cmd + if (dm_get_pid_of_cmd(dep_cmd, dep_pid, sizeof(dep_pid))) { + // ... and handle the dep_cmd process first + dm_handle_process(dep_pid, depth + 1); + } + } + + // remove entry of process in DM_DIR + if (remove(process_dm_path) != 0) { + dprintf("%s: Couldnt remove %s\n", __FUNCTION__, process_dm_path); + } + + // restart using process_cmd + dprintf("%s Restarting process %s\n", __FUNCTION__, process_cmd); + system(process_cmd); + + return TRUE; +} + +static unsigned char dm_match_cmd(char *pid, char *process_cmd_needle) +{ + char process_dm_path[DM_BUF_SZ]; + char dep_cmd[DM_BUF_SZ] = {0}; + char process_cmd[DM_BUF_SZ] = {0}; + char dep_pid[DM_BUF_SZ] = {0}; + + snprintf(process_dm_path, sizeof(process_dm_path), "%s/%s", DM_DIR, pid); + + dm_read_pid_info_file(process_dm_path, dep_cmd, sizeof(dep_cmd), + process_cmd, sizeof(process_cmd)); + + if (strncmp(process_cmd, process_cmd_needle, sizeof(process_cmd)) == 0) { + return TRUE; + } + + return FALSE; +} + +static unsigned char dm_get_pid_of_cmd(char *dep_cmd, char *dep_pid, size_t dep_pid_sz) +{ + DIR *dir; + struct dirent *de; + + if ((dir = opendir(DM_DIR)) == NULL) { + dprintf("%s error opening %s\n", __FUNCTION__, DM_DIR); + return FALSE; + } + + while ((de = readdir(dir)) != NULL) { + // walk through entries in DM_DIR and find respective pid + if (de->d_name[0] == '.') + continue; + if (dm_match_cmd(de->d_name, dep_cmd)) { + strncpy(dep_pid, de->d_name, dep_pid_sz); + closedir(dir); + return TRUE; + } + } + + closedir(dir); + return FALSE; +} + +static void dm_watchdog() +{ + DIR *dir; + struct dirent *de; + + if ((dir = opendir(DM_DIR)) == NULL) { + dprintf("%s error opening %s\n", __FUNCTION__, DM_DIR); + return; + } + + while ((de = readdir(dir)) != NULL) { + // walk through entries in DM_DIR and call dm_handle_process on each + if (de->d_name[0] == '.') + continue; + dm_handle_process(de->d_name, 0); + } + closedir(dir); +} + +int main(int argc, char **argv) +{ + _mod_name = argv[0]; + char *nv_str; + + dhd_monitor_msglevel = strtoul(nvram_safe_get("dhd_monitor_msglevel"), NULL, 0); + +//#if defined(__CONFIG_DHDAP__) +#if 1 + if (argc < 2) { + printf("%s: error no backup dir.\n", _mod_name); + usage(_mod_name); + } else { + _backup_dir = argv[1]; + } + + if (signal(SIGUSR1, sig_handler) == SIG_ERR) { + printf("%s: error setting up signal1 handler.\n", _mod_name); + return -1; + } + if (signal(SIGUSR2, sig_handler) == SIG_ERR) { + printf("%s: error setting up signal2 handler.\n", _mod_name); + return -1; + } +#endif /* __CONFIG_DHDAP__ */ + nv_str = (char *)nvram_get("debug_monitor_disable_app_restart"); + + if (nv_str && (nv_str[0] == '1') && (nv_str[1] == '\0')) { + dbg_mon_disab_rstrt = TRUE; + } + if (daemon(1, 1) == -1) { + printf("%s: error daemonizing.\n", _mod_name); + } else { + unsigned int tick = 0; + while (1) { + if (!dbg_mon_disab_rstrt && + (tick++ % DM_INTERVAL) == 0) { + dm_watchdog(); + } + sleep(1); + } + } + + return 0; +} diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/prebuilt/debug_monitor b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/prebuilt/debug_monitor new file mode 100755 index 00000000000..f8f6b13998b Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhd_monitor/prebuilt/debug_monitor differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/Makefile new file mode 100644 index 00000000000..382131ff607 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/Makefile @@ -0,0 +1,49 @@ + +# +# In most cases, you only need to modify this first section. +# +EXE = dry +LCFLAGS = -O3 +all dynamic install: $(EXE) generic_exe_install + +clean: generic_clean + rm -f $(INSTALL_DIR)/bin/$(EXE) + + + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) + +include $(BUILD_DIR)/make.common + + +ifeq ("$(ARCH)","mips") + LCFLAGS += -mno-shared +endif + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# +$(EXE): dry.c + $(CC) $(LCFLAGS) -c dry.c -o dry.o + $(CC) $(LCFLAGS) -DPASS2 dry.c dry.o -o $(EXE) + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +-include $(OBJS:.o=.d) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/autodetect new file mode 100644 index 00000000000..8f9e4a82e70 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/autodetect @@ -0,0 +1,2 @@ +condition:ifneq ($(strip $(BENCHMARKS_SMP)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/dry.c b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/dry.c new file mode 100644 index 00000000000..b1957c6ab1f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dhrystone/dry.c @@ -0,0 +1,1329 @@ +/****************** "DHRYSTONE" Benchmark Program ***************************/ +#define Version "C, Version 2.2" +/* File: dhry_1.c (part 2 of 3) + * Author: Reinhold P. Weicker + * Siemens Nixdorf, Paderborn/Germany + * weicker@specbench.org + * Date: May 25, 1988 + * Modified: Steven Pemberton, CWI, Amsterdam; Steven.Pemberton@cwi.nl + * Date: October, 1993; March 1995 + * Included both files into one source, that gets compiled + * in two passes. Made program auto-compiling, and auto-running, + * and generally made it much easier to use. + * + * Original Version (in Ada) published in + * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), + * pp. 1013 - 1030, together with the statistics + * on which the distribution of statements etc. is based. + * + * In this C version, the following C library functions are used: + * - strcpy, strcmp (inside the measurement loop) + * - printf, scanf (outside the measurement loop) + * In addition, Berkeley UNIX system calls "times ()" or "time ()" + * are used for execution time measurement. For measurements + * on other systems, these calls have to be changed. + * + * Collection of Results: + * Reinhold Weicker (address see above) and + * + * Rick Richardson + * PC Research. Inc. + * 94 Apple Orchard Drive + * Tinton Falls, NJ 07724 + * Phone: (201) 389-8963 (9-17 EST) + * Usenet: ...!uunet!pcrat!rick + * + * Please send results to Rick Richardson and/or Reinhold Weicker. + * Complete information should be given on hardware and software used. + * Hardware information includes: Machine type, CPU, type and size + * of caches; for microprocessors: clock frequency, memory speed + * (number of wait states). + * Software information includes: Compiler (and runtime library) + * manufacturer and version, compilation switches, OS version. + * The Operating System version may give an indication about the compiler; + * Dhrystone itself performs no OS calls in the measurement loop. + * + * The complete output generated by the program should be mailed + * such that at least some checks for correctness can be made. + * + *************************************************************************** + * + * Defines: The following "Defines" are possible: + * -DREG (default: Not defined) + * As an approximation to what an average C programmer + * might do, causes the "register" storage class to be applied + * - for local variables, if they are used (dynamically) + * five or more times + * - for parameters if they are used (dynamically) + * six or more times + * Note that an optimal "register" strategy is + * compiler-dependent, and that "register" declarations + * do not necessarily lead to faster execution. + * -DNOSTRUCTASSIGN (default: Not defined) + * Define if the C compiler does not support + * assignment of structures. + * -DNOENUMS (default: Not defined) + * Define if the C compiler does not support + * enumeration types. + * -DTIMES (default) + * -DTIME + * The "times" function of UNIX (returning process times) + * or the "time" function (returning wallclock time) + * is used for measurement. + * For single user machines, "time ()" is adequate. For + * multi-user machines where you cannot get single-user + * access, use the "times ()" function. If you have + * neither, use a stopwatch in the dead of night. + * "printf"s are provided marking the points "Start Timer" + * and "Stop Timer". DO NOT use the UNIX "time(1)" + * command, as this will measure the total time to + * run this program, which will (erroneously) include + * the time to allocate storage (malloc) and to perform + * the initialization. + * -DHZ=nnn + * In Berkeley UNIX, the function "times" returns process + * time in 1/HZ seconds, with HZ = 60 for most systems. + * CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY + * A VALUE. + * + *************************************************************************** + * + * History: Version C/2.1 was made for two reasons: + * + * 1) There was an obvious need for a common C version of + * Dhrystone, since C is at present the most popular system + * programming language for the class of processors + * (microcomputers, minicomputers) where Dhrystone is used most. + * There should be, as far as possible, only one C version of + * Dhrystone such that results can be compared without + * restrictions. In the past, the C versions distributed + * by Rick Richardson (Version 1.1) and by Reinhold Weicker + * had small (though not significant) differences. + * + * 2) As far as it is possible without changes to the Dhrystone + * statistics, optimizing compilers should be prevented from + * removing significant statements. + * + * This C version has been developed in cooperation with + * Rick Richardson (Tinton Falls, NJ), it incorporates many + * ideas from the "Version 1.1" distributed previously by + * him over the UNIX network Usenet. + * I also thank Chaim Benedelac (National Semiconductor), + * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), + * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) + * for their help with comments on earlier versions of the + * benchmark. + * + * Changes: In the initialization part, this version follows mostly + * Rick Richardson's version distributed via Usenet, not the + * version distributed earlier via floppy disk by Reinhold Weicker. + * As a concession to older compilers, names have been made + * unique within the first 8 characters. + * Inside the measurement loop, this version follows the + * version previously distributed by Reinhold Weicker. + * + * At several places in the benchmark, code has been added, + * but within the measurement loop only in branches that + * are not executed. The intention is that optimizing compilers + * should be prevented from moving code out of the measurement + * loop, or from removing code altogether. Since the statements + * that are executed within the measurement loop have NOT been + * changed, the numbers defining the "Dhrystone distribution" + * (distribution of statements, operand types and locality) + * still hold. Except for sophisticated optimizing compilers, + * execution times for this version should be the same as + * for previous versions. + * + * Since it has proven difficult to subtract the time for the + * measurement loop overhead in a correct way, the loop check + * has been made a part of the benchmark. This does have + * an impact - though a very minor one - on the distribution + * statistics which have been updated for this version. + * + * All changes within the measurement loop are described + * and discussed in the companion paper "Rationale for + * Dhrystone version 2". + * + * Because of the self-imposed limitation that the order and + * distribution of the executed statements should not be + * changed, there are still cases where optimizing compilers + * may not generate code for some statements. To a certain + * degree, this is unavoidable for small synthetic benchmarks. + * Users of the benchmark are advised to check code listings + * whether code is generated for all statements of Dhrystone. + * + * Version 2.1 is identical to version 2.0 distributed via + * the UNIX network Usenet in March 1988 except that it corrects + * some minor deficiencies that were found by users of version 2.0. + * The only change within the measurement loop is that a + * non-executed "else" part was added to the "if" statement in + * Func_3, and a non-executed "else" part removed from Proc_3. + * + * Version C/2.2, Steven Pemberton, October 1993 + * Functionally, identical to version 2.2; the changes are in + * how you compile and use it: + * - Everything is in one file now, but compiled in 2 passes + * - Compile (and run) by running the file through the shell: 'sh dhry.c" + * - Uses the system definition of HZ if one can be found + * - HZ must be defined, otherwise it won't compile (no defaults here) + * - The (uninteresting) output is printed to stderr (dhry2 > /dev/null) + * - The number of loops is passed as a parameter, rather than read + * (dhry2 500000) + * - If the number of loops is insufficient to get a good result, + * it repeats it with loops*10 until it is enough (rather than just + * stopping) + * - Output says which sort of clock it is using, and the HZ value + * - You can use -DREG instead of the -DREG=register of previous versions + * - Some stylistic cleanups. + * + *************************************************************************** + * + * Compilation model and measurement (IMPORTANT): + * + * The following "ground rules" apply for measurements: + * - Separate compilation + * - No procedure merging + * - Otherwise, compiler optimizations are allowed but should be indicated + * - Default results are those without register declarations + * See the companion paper "Rationale for Dhrystone Version 2" for a more + * detailed discussion of these ground rules. + * + * For 16-Bit processors (e.g. 80186, 80286), times for all compilation + * models ("small", "medium", "large" etc.) should be given if possible, + * together with a definition of these models for the compiler system used. + * + ************************************************************************** + * + * Dhrystone (C version) statistics: + * + * [Comment from the first distribution, updated for version 2. + * Note that because of language differences, the numbers are slightly + * different from the Ada version.] + * + * The following program contains statements of a high level programming + * language (here: C) in a distribution considered representative: + * + * assignments 52 (51.0 %) + * control statements 33 (32.4 %) + * procedure, function calls 17 (16.7 %) + * + * 103 statements are dynamically executed. The program is balanced with + * respect to the three aspects: + * + * - statement type + * - operand type + * - operand locality + * operand global, local, parameter, or constant. + * + * The combination of these three aspects is balanced only approximately. + * + * 1. Statement Type: + * ----------------- number + * + * V1 = V2 9 + * (incl. V1 = F(..) + * V = Constant 12 + * Assignment, 7 + * with array element + * Assignment, 6 + * with record component + * -- + * 34 34 + * + * X = Y +|-|"&&"|"|" Z 5 + * X = Y +|-|"==" Constant 6 + * X = X +|- 1 3 + * X = Y *|/ Z 2 + * X = Expression, 1 + * two operators + * X = Expression, 1 + * three operators + * -- + * 18 18 + * + * if .... 14 + * with "else" 7 + * without "else" 7 + * executed 3 + * not executed 4 + * for ... 7 | counted every time + * while ... 4 | the loop condition + * do ... while 1 | is evaluated + * switch ... 1 + * break 1 + * declaration with 1 + * initialization + * -- + * 34 34 + * + * P (...) procedure call 11 + * user procedure 10 + * library procedure 1 + * X = F (...) + * function call 6 + * user function 5 + * library function 1 + * -- + * 17 17 + * --- + * 103 + * + * The average number of parameters in procedure or function calls + * is 1.82 (not counting the function values aX * + * + * 2. Operators + * ------------ + * number approximate + * percentage + * + * Arithmetic 32 50.8 + * + * + 21 33.3 + * - 7 11.1 + * * 3 4.8 + * / (int div) 1 1.6 + * + * Comparison 27 42.8 + * + * == 9 14.3 + * /= 4 6.3 + * > 1 1.6 + * < 3 4.8 + * >= 1 1.6 + * <= 9 14.3 + * + * Logic 4 6.3 + * + * && (AND-THEN) 1 1.6 + * | (OR) 1 1.6 + * ! (NOT) 2 3.2 + * + * -- ----- + * 63 100.1 + * + * + * 3. Operand Type (counted once per operand reference): + * --------------- + * number approximate + * percentage + * + * Integer 175 72.3 % + * Character 45 18.6 % + * Pointer 12 5.0 % + * String30 6 2.5 % + * Array 2 0.8 % + * Record 2 0.8 % + * --- ------- + * 242 100.0 % + * + * When there is an access path leading to the final operand (e.g. a record + * component), only the final data type on the access path is counted. + * + * + * 4. Operand Locality: + * ------------------- + * number approximate + * percentage + * + * local variable 114 47.1 % + * global variable 22 9.1 % + * parameter 45 18.6 % + * value 23 9.5 % + * reference 22 9.1 % + * function result 6 2.5 % + * constant 55 22.7 % + * --- ------- + * 242 100.0 % + * + * The program does not compute anything meaningful, but it is syntactically + * and semantically correct. All variables have a value assigned to them + * before they are used as a source operand. + * + * There has been no explicit effort to account for the effects of a + * cache, or to balance the use of long or short displacements for code or + * data. + * + *************************************************************************** + */ +#define CONFIG_MIPS_BRCM + +/* Compiler and system dependent definitions: */ + +/* variables for time measurement: */ + +#if 1 + +#ifdef CONFIG_MIPS_BRCM +// Need to define GNU_SOURCE before including sched.h +// do it lower in the C file to avoid affecting other header files. +#define _GNU_SOURCE +#include +#endif //CONFIG_MIPS_BRCM + +#include +#define CLOCK_TYPE "gettimeofday()" +#undef HZ +#define HZ (1000) /* time() returns time in seconds */ +struct timeval ttmp; +#define Too_Small_Time 2*HZ /* Measurements should last at least 2 seconds */ +#define Start_Timer() gettimeofday(&ttmp, NULL); Begin_Time = (unsigned int)ttmp.tv_sec*1000 + (unsigned int)ttmp.tv_usec/1000 +#define Stop_Timer() gettimeofday(&ttmp, NULL); End_Time = (unsigned int)ttmp.tv_sec*1000 + (unsigned int)ttmp.tv_usec/1000 + +#endif + +#if 0 + +#ifdef TIME + +#define CLOCK_TYPE "time()" +#undef HZ +#define HZ (1) /* time() returns time in seconds */ +extern long time(); /* see library function "time" */ +#define Too_Small_Time 2 /* Measurements should last at least 2 seconds */ +#define Start_Timer() Begin_Time = time ( (long *) 0) +#define Stop_Timer() End_Time = time ( (long *) 0) + +#else + +#ifdef MSC_CLOCK /* Use Microsoft C hi-res clock */ + +#undef HZ +#undef TIMES +#include +#define HZ CLK_TCK +#define CLOCK_TYPE "MSC clock()" +extern clock_t clock(); +#define Too_Small_Time (2*HZ) +#define Start_Timer() Begin_Time = clock() +#define Stop_Timer() End_Time = clock() + +#else + /* Use times(2) time function unless */ + /* explicitly defined otherwise */ +#define CLOCK_TYPE "times()" +#include +#include +#ifndef HZ /* Added by SP 900619 */ +#include /* If your system doesn't have this, use -DHZ=xxx */ +#else + *** You must define HZ!!! *** +#endif /* HZ */ +#ifndef PASS2 +struct tms time_info; +#endif +/*extern int times ();*/ + /* see library function "times" */ +#define Too_Small_Time (2*HZ) + /* Measurements should last at least about 2 seconds */ +#define Start_Timer() times(&time_info); Begin_Time=(long)time_info.tms_utime +#define Stop_Timer() times(&time_info); End_Time = (long)time_info.tms_utime + +#endif /* MSC_CLOCK */ +#endif /* TIME */ + +#endif + +#define Mic_secs_Per_Second 1000000.0 +#define NUMBER_OF_RUNS 50000 /* Default number of runs */ + +#ifdef NOSTRUCTASSIGN +#define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) +#else +#define structassign(d, s) d = s +#endif + +#ifdef NOENUM +#define Ident_1 0 +#define Ident_2 1 +#define Ident_3 2 +#define Ident_4 3 +#define Ident_5 4 + typedef int Enumeration; +#else + typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5} + Enumeration; +#endif + /* for boolean and enumeration types in Ada, Pascal */ + +/* General definitions: */ + +#include +#include +#include + /* for strcpy, strcmp */ + +#define Null 0 + /* Value of a Null pointer */ +#define true 1 +#define false 0 + +typedef int One_Thirty; +typedef int One_Fifty; +typedef char Capital_Letter; +typedef int Boolean; +typedef char Str_30 [31]; +typedef int Arr_1_Dim [50]; +typedef int Arr_2_Dim [50] [50]; + +typedef struct record + { + struct record *Ptr_Comp; + Enumeration Discr; + union { + struct { + Enumeration Enum_Comp; + int Int_Comp; + char Str_Comp [31]; + } var_1; + struct { + Enumeration E_Comp_2; + char Str_2_Comp [31]; + } var_2; + struct { + char Ch_1_Comp; + char Ch_2_Comp; + } var_3; + } variant; + } Rec_Type, *Rec_Pointer; + +#ifndef PASS2 + +/* Global Variables: */ + +Rec_Pointer Ptr_Glob, + Next_Ptr_Glob; +int Int_Glob; +Boolean Bool_Glob; +char Ch_1_Glob, + Ch_2_Glob; +int Arr_1_Glob [50]; +int Arr_2_Glob [50] [50]; + +#ifdef CONFIG_MIPS_BRCM +int nor_multiplier=200; // Number_of_Runs multiplier, default was 200 +int run_rt_fifo=0; +int bind_cpu=0; +int threadId; +#endif //CONFIG_MIPS_BRCM + +extern void *malloc (); +Enumeration Func_1 (); + /* forward declaration necessary since Enumeration may not simply be int */ + +#ifndef REG + Boolean Reg = false; +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else + Boolean Reg = true; +#undef REG +#define REG register +#endif + +Boolean Done; + +long Begin_Time, + End_Time, + User_Time; +float Microseconds, + Dhrystones_Per_Second; + +/* end of variables for time measurement */ + +#if 1 + +main (argc, argv) int argc; char *argv[]; +{ + + int nthread=1; + int ret = -1; + int pid; + volatile i; + + if (argc == 1) { + ret = 0; + } + else if (argc >= 2) + { +#ifdef CONFIG_MIPS_BRCM + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { + ret = 1; + } + else +#endif //CONFIG_MIPS_BRCM + if (sscanf(argv[1], "%d", &nthread) == 1) { + if (nthread >0) { + ret = 0; + } + } + } + +#ifdef CONFIG_MIPS_BRCM + if (ret == 0 && argc > 2) { + // parse additional arguments + int c=argc-2; + int idx=2; + while (ret == 0 && c > 0) { + if (!strcmp(argv[idx], "-m")) { + idx++; + c--; + if (c > 0) + nor_multiplier = atoi(argv[idx++]); + else + ret = 1; + c--; + } + else if (!strcmp(argv[idx], "-r")) { + run_rt_fifo = 1; + idx++; + c--; + } + else if (!strcmp(argv[idx], "-b")) { + bind_cpu = 1; + idx++; + c--; + } + else + ret = 1; + } + } +#endif //CONFIG_MIPS_BRCM + + if (ret != 0) { + printf ("Usage: %s [number of processes]\n", argv[0]); +#ifdef CONFIG_MIPS_BRCM + printf (" bcm extensions: after the number of processes you can specify:\n"); + printf (" -m multiplier (to make drystone run longer, default is 200\n"); + printf (" -r (run as high priority real time FIFO process\n"); + printf (" -b (bind processes to alternating CPU's\n"); +#endif //CONFIG_MIPS_BRCM + exit (ret); + } + +#ifdef CONFIG_MIPS_BRCM + printf("Number_of_Runs multipler = %d (default 200)\n", nor_multiplier); + printf("Run as Real-time FIFO process = %d\n", run_rt_fifo); + printf("Bind to CPU = %d\n", bind_cpu); +#endif //CONFIG_MIPS_BRCM + + + for (nthread; nthread >0; nthread --) { + pid = fork(); + if (pid == 0) { +#ifdef CONFIG_MIPS_BRCM + threadId = nthread; + if (run_rt_fifo) { + int rc; + struct sched_param sched = {0}; + sched.__sched_priority = 90; + printf("thread %d: setting rt fifo\n", nthread); + rc = sched_setscheduler(0, SCHED_FIFO, &sched); + if (rc < 0) { + printf("sched_setscheduler for rt failed, rc=%d\n", rc); + exit(-1); + } + } + if (bind_cpu) { + int rc; + cpu_set_t mask; + CPU_ZERO(&mask); + if (nthread % 2 == 0) { + CPU_SET(0, &mask); printf("thread %d: bind to 0\n", nthread); + } else { + CPU_SET(1, &mask); printf("thread %d: bind to 1\n", nthread); + } + rc = sched_setaffinity(0, sizeof(cpu_set_t), &mask); + if (rc < 0) { + printf("sched_setaffinity failed, rc=%d\n", rc); + exit(-1); + } + } +#endif //CONFIG_MIPS_BRCM + printf("Dhrystone process pid %d\n", getpid()); + for (i=0;i<1000*1000*20; i++) {} + __main(); + for (i=0;i<1000*1000*20; i++) {} + break; + } + } + + return ret; +} + +__main() +{ + + One_Fifty Int_1_Loc; + REG One_Fifty Int_2_Loc; + One_Fifty Int_3_Loc; + REG char Ch_Index; + Enumeration Enum_Loc; + Str_30 Str_1_Loc; + Str_30 Str_2_Loc; + REG int Run_Index; + REG int Number_Of_Runs; + + volatile char buf[4096]; + + Number_Of_Runs = NUMBER_OF_RUNS*nor_multiplier; + + /* Initializations */ + + Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + + Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; + Ptr_Glob->Discr = Ident_1; + Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; + Ptr_Glob->variant.var_1.Int_Comp = 40; + strcpy (Ptr_Glob->variant.var_1.Str_Comp, + "DHRYSTONE PROGRAM, SOME STRING"); + strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); + + Arr_2_Glob [8][7] = 10; + /* Was missing in published program. Without this statement, */ + /* Arr_2_Glob [8][7] would have an undefined value. */ + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ + /* overflow may occur for this array element. */ + + printf ("\n"); + printf ("Dhrystone Benchmark, Version %s\n", Version); + if (Reg) + { + printf ("Program compiled with 'register' attribute\n"); + } + else + { + printf ("Program compiled without 'register' attribute\n"); + } + printf ("Using %s, HZ=%d\n", CLOCK_TYPE, HZ); + printf ("\n"); + + Done = false; + while (!Done) { + + printf ("Trying %d runs through Dhrystone:\n", Number_Of_Runs); + + /***************/ + /* Start timer */ + /***************/ + + Start_Timer(); + + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) + { + + Proc_5(); + Proc_4(); + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ + Int_1_Loc = 2; + Int_2_Loc = 3; + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); + Enum_Loc = Ident_2; + Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); + /* Bool_Glob == 1 */ + while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ + { + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; + /* Int_3_Loc == 7 */ + Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); + /* Int_3_Loc == 7 */ + Int_1_Loc += 1; + } /* while */ + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); + /* Int_Glob == 5 */ + Proc_1 (Ptr_Glob); + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) + /* loop body executed twice */ + { + if (Enum_Loc == Func_1 (Ch_Index, 'C')) + /* then, not executed */ + { + Proc_6 (Ident_1, &Enum_Loc); + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); + Int_2_Loc = Run_Index; + Int_Glob = Run_Index; + } + } + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Int_2_Loc = Int_2_Loc * Int_1_Loc; + Int_1_Loc = Int_2_Loc / Int_3_Loc; + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ + Proc_2 (&Int_1_Loc); + /* Int_1_Loc == 5 */ + + } /* loop "for Run_Index" */ + + /**************/ + /* Stop timer */ + /**************/ + + Stop_Timer(); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + printf ("Measured time too small to obtain meaningful results\n"); + Number_Of_Runs = Number_Of_Runs * 10; + printf ("\n"); + } else Done = true; + } + + sprintf (buf, "Final values of the variables used in the benchmark:\n"); + sprintf (buf, "\n"); + sprintf(buf, "Int_Glob: %d\n", Int_Glob); + sprintf(buf, " should be: %d\n", 5); + sprintf(buf, "Bool_Glob: %d\n", Bool_Glob); + sprintf(buf, " should be: %d\n", 1); + sprintf(buf, "Ch_1_Glob: %c\n", Ch_1_Glob); + sprintf(buf, " should be: %c\n", 'A'); + sprintf(buf, "Ch_2_Glob: %c\n", Ch_2_Glob); + sprintf(buf, " should be: %c\n", 'B'); + sprintf(buf, "Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + sprintf(buf, " should be: %d\n", 7); + sprintf(buf, "Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + sprintf(buf, " should be: Number_Of_Runs + 10\n"); + sprintf(buf, "Ptr_Glob->\n"); + sprintf(buf, " Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); + sprintf(buf, " should be: (implementation-dependent)\n"); + sprintf(buf, " Discr: %d\n", Ptr_Glob->Discr); + sprintf(buf, " should be: %d\n", 0); + sprintf(buf, " Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); + sprintf(buf, " should be: %d\n", 2); + sprintf(buf, " Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); + sprintf(buf, " should be: %d\n", 17); + sprintf(buf, " Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); + sprintf(buf, " should be: DHRYSTONE PROGRAM, SOME STRING\n"); + sprintf(buf, "Next_Ptr_Glob->\n"); + sprintf(buf, " Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); + sprintf(buf, " should be: (implementation-dependent), same as above\n"); + sprintf(buf, " Discr: %d\n", Next_Ptr_Glob->Discr); + sprintf(buf, " should be: %d\n", 0); + sprintf(buf, " Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); + sprintf(buf, " should be: %d\n", 1); + sprintf(buf, " Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); + sprintf(buf, " should be: %d\n", 18); + sprintf(buf, " Str_Comp: %s\n", + Next_Ptr_Glob->variant.var_1.Str_Comp); + sprintf(buf, " should be: DHRYSTONE PROGRAM, SOME STRING\n"); + sprintf(buf, "Int_1_Loc: %d\n", Int_1_Loc); + sprintf(buf, " should be: %d\n", 5); + sprintf(buf, "Int_2_Loc: %d\n", Int_2_Loc); + sprintf(buf, " should be: %d\n", 13); + sprintf(buf, "Int_3_Loc: %d\n", Int_3_Loc); + sprintf(buf, " should be: %d\n", 7); + sprintf(buf, "Enum_Loc: %d\n", Enum_Loc); + sprintf(buf, " should be: %d\n", 1); + sprintf(buf, "Str_1_Loc: %s\n", Str_1_Loc); + sprintf(buf, " should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + sprintf(buf, "Str_2_Loc: %s\n", Str_2_Loc); + sprintf(buf, " should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + sprintf(buf, "\n"); + + Microseconds = (float) User_Time * Mic_secs_Per_Second / ((float) HZ * ((float) Number_Of_Runs)); + Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) / (float) User_Time; + +#ifdef CONFIG_MIPS_BRCM + printf ("Thread %d: ", threadId); +#endif + printf ("Dhrystones per Second: %6.0f DMIPS: %6.0f\n", Dhrystones_Per_Second, Dhrystones_Per_Second/1757.0); + +} + +#else + +main (argc, argv) int argc; char *argv[]; +/*****/ + + /* main program, corresponds to procedures */ + /* Main and Proc_0 in the Ada version */ +{ + One_Fifty Int_1_Loc; + REG One_Fifty Int_2_Loc; + One_Fifty Int_3_Loc; + REG char Ch_Index; + Enumeration Enum_Loc; + Str_30 Str_1_Loc; + Str_30 Str_2_Loc; + REG int Run_Index; + REG int Number_Of_Runs; + + /* Arguments */ + if (argc > 2) + { + printf ("Usage: %s [number of loops]\n", argv[0]); + exit (1); + } + if (argc == 2) + { + Number_Of_Runs = atoi (argv[1]); + } else + { + Number_Of_Runs = NUMBER_OF_RUNS; + } + if (Number_Of_Runs <= 0) + { + Number_Of_Runs = NUMBER_OF_RUNS; + } + + /* Initializations */ + + Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + + Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; + Ptr_Glob->Discr = Ident_1; + Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; + Ptr_Glob->variant.var_1.Int_Comp = 40; + strcpy (Ptr_Glob->variant.var_1.Str_Comp, + "DHRYSTONE PROGRAM, SOME STRING"); + strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); + + Arr_2_Glob [8][7] = 10; + /* Was missing in published program. Without this statement, */ + /* Arr_2_Glob [8][7] would have an undefined value. */ + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ + /* overflow may occur for this array element. */ + + printf ("\n"); + printf ("Dhrystone Benchmark, Version %s\n", Version); + if (Reg) + { + printf ("Program compiled with 'register' attribute\n"); + } + else + { + printf ("Program compiled without 'register' attribute\n"); + } + printf ("Using %s, HZ=%d\n", CLOCK_TYPE, HZ); + printf ("\n"); + + Done = false; + while (!Done) { + + printf ("Trying %d runs through Dhrystone:\n", Number_Of_Runs); + + /***************/ + /* Start timer */ + /***************/ + + Start_Timer(); + + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) + { + + Proc_5(); + Proc_4(); + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ + Int_1_Loc = 2; + Int_2_Loc = 3; + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); + Enum_Loc = Ident_2; + Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); + /* Bool_Glob == 1 */ + while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ + { + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; + /* Int_3_Loc == 7 */ + Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); + /* Int_3_Loc == 7 */ + Int_1_Loc += 1; + } /* while */ + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); + /* Int_Glob == 5 */ + Proc_1 (Ptr_Glob); + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) + /* loop body executed twice */ + { + if (Enum_Loc == Func_1 (Ch_Index, 'C')) + /* then, not executed */ + { + Proc_6 (Ident_1, &Enum_Loc); + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); + Int_2_Loc = Run_Index; + Int_Glob = Run_Index; + } + } + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Int_2_Loc = Int_2_Loc * Int_1_Loc; + Int_1_Loc = Int_2_Loc / Int_3_Loc; + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ + Proc_2 (&Int_1_Loc); + /* Int_1_Loc == 5 */ + + } /* loop "for Run_Index" */ + + /**************/ + /* Stop timer */ + /**************/ + + Stop_Timer(); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + printf ("Measured time too small to obtain meaningful results\n"); + Number_Of_Runs = Number_Of_Runs * 10; + printf ("\n"); + } else Done = true; + } + + sprintf(buf, "Final values of the variables used in the benchmark:\n"); + sprintf(buf, "\n"); + sprintf(buf, "Int_Glob: %d\n", Int_Glob); + sprintf(buf, " should be: %d\n", 5); + sprintf(buf, "Bool_Glob: %d\n", Bool_Glob); + sprintf(buf, " should be: %d\n", 1); + sprintf(buf, "Ch_1_Glob: %c\n", Ch_1_Glob); + sprintf(buf, " should be: %c\n", 'A'); + sprintf(buf, "Ch_2_Glob: %c\n", Ch_2_Glob); + sprintf(buf, " should be: %c\n", 'B'); + sprintf(buf, "Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + sprintf(buf, " should be: %d\n", 7); + sprintf(buf, "Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + sprintf(buf, " should be: Number_Of_Runs + 10\n"); + sprintf(buf, "Ptr_Glob->\n"); + sprintf(buf, " Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); + sprintf(buf, " should be: (implementation-dependent)\n"); + sprintf(buf, " Discr: %d\n", Ptr_Glob->Discr); + sprintf(buf, " should be: %d\n", 0); + sprintf(buf, " Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); + sprintf(buf, " should be: %d\n", 2); + sprintf(buf, " Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); + sprintf(buf, " should be: %d\n", 17); + sprintf(buf, " Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); + sprintf(buf, " should be: DHRYSTONE PROGRAM, SOME STRING\n"); + sprintf(buf, "Next_Ptr_Glob->\n"); + sprintf(buf, " Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); + sprintf(buf, " should be: (implementation-dependent), same as above\n"); + sprintf(buf, " Discr: %d\n", Next_Ptr_Glob->Discr); + sprintf(buf, " should be: %d\n", 0); + sprintf(buf, " Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); + sprintf(buf, " should be: %d\n", 1); + sprintf(buf, " Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); + sprintf(buf, " should be: %d\n", 18); + sprintf(buf, " Str_Comp: %s\n", + Next_Ptr_Glob->variant.var_1.Str_Comp); + sprintf(buf, " should be: DHRYSTONE PROGRAM, SOME STRING\n"); + sprintf(buf, "Int_1_Loc: %d\n", Int_1_Loc); + sprintf(buf, " should be: %d\n", 5); + sprintf(buf, "Int_2_Loc: %d\n", Int_2_Loc); + sprintf(buf, " should be: %d\n", 13); + sprintf(buf, "Int_3_Loc: %d\n", Int_3_Loc); + sprintf(buf, " should be: %d\n", 7); + sprintf(buf, "Enum_Loc: %d\n", Enum_Loc); + sprintf(buf, " should be: %d\n", 1); + sprintf(buf, "Str_1_Loc: %s\n", Str_1_Loc); + sprintf(buf, " should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + sprintf(buf, "Str_2_Loc: %s\n", Str_2_Loc); + sprintf(buf, " should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + sprintf(buf, "\n"); + + + Microseconds = (float) User_Time * Mic_secs_Per_Second + / ((float) HZ * ((float) Number_Of_Runs)); + Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) + / (float) User_Time; + + printf ("Microseconds for one run through Dhrystone: "); + printf ("%10.1f \n", Microseconds); + printf ("Dhrystones per Second: "); + printf ("%10.0f \n", Dhrystones_Per_Second); + printf ("\n"); + +} + +#endif + +Proc_1 (Ptr_Val_Par) +/******************/ + +REG Rec_Pointer Ptr_Val_Par; + /* executed once */ +{ + REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; + /* == Ptr_Glob_Next */ + /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ + /* corresponds to "rename" in Ada, "with" in Pascal */ + + structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); + Ptr_Val_Par->variant.var_1.Int_Comp = 5; + Next_Record->variant.var_1.Int_Comp + = Ptr_Val_Par->variant.var_1.Int_Comp; + Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; + Proc_3 (&Next_Record->Ptr_Comp); + /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp + == Ptr_Glob->Ptr_Comp */ + if (Next_Record->Discr == Ident_1) + /* then, executed */ + { + Next_Record->variant.var_1.Int_Comp = 6; + Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, + &Next_Record->variant.var_1.Enum_Comp); + Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; + Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, + &Next_Record->variant.var_1.Int_Comp); + } + else /* not executed */ + structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); +} /* Proc_1 */ + + +Proc_2 (Int_Par_Ref) +/******************/ + /* executed once */ + /* *Int_Par_Ref == 1, becomes 4 */ + +One_Fifty *Int_Par_Ref; +{ + One_Fifty Int_Loc; + Enumeration Enum_Loc; + + Int_Loc = *Int_Par_Ref + 10; + do /* executed once */ + if (Ch_1_Glob == 'A') + /* then, executed */ + { + Int_Loc -= 1; + *Int_Par_Ref = Int_Loc - Int_Glob; + Enum_Loc = Ident_1; + } /* if */ + while (Enum_Loc != Ident_1); /* true */ +} /* Proc_2 */ + + +Proc_3 (Ptr_Ref_Par) +/******************/ + /* executed once */ + /* Ptr_Ref_Par becomes Ptr_Glob */ + +Rec_Pointer *Ptr_Ref_Par; + +{ + if (Ptr_Glob != Null) + /* then, executed */ + *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; + Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); +} /* Proc_3 */ + + +Proc_4 () /* without parameters */ +/*******/ + /* executed once */ +{ + Boolean Bool_Loc; + + Bool_Loc = Ch_1_Glob == 'A'; + Bool_Glob = Bool_Loc | Bool_Glob; + Ch_2_Glob = 'B'; +} /* Proc_4 */ + + +Proc_5 () /* without parameters */ +/*******/ + /* executed once */ +{ + Ch_1_Glob = 'A'; + Bool_Glob = false; +} /* Proc_5 */ + + + /* Procedure for the assignment of structures, */ + /* if the C compiler doesn't support this feature */ +#ifdef NOSTRUCTASSIGN +memcpy (d, s, l) +register char *d; +register char *s; +register int l; +{ + while (l--) *d++ = *s++; +} +#endif + + +#else /* PASS2 */ + +#ifndef REG +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else +#undef REG +#define REG register +#endif + +extern int Int_Glob; +extern char Ch_1_Glob; + + +Proc_6 (Enum_Val_Par, Enum_Ref_Par) +/*********************************/ + /* executed once */ + /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ + +Enumeration Enum_Val_Par; +Enumeration *Enum_Ref_Par; +{ + *Enum_Ref_Par = Enum_Val_Par; + if (! Func_3 (Enum_Val_Par)) + /* then, not executed */ + *Enum_Ref_Par = Ident_4; + switch (Enum_Val_Par) + { + case Ident_1: + *Enum_Ref_Par = Ident_1; + break; + case Ident_2: + if (Int_Glob > 100) + /* then */ + *Enum_Ref_Par = Ident_1; + else *Enum_Ref_Par = Ident_4; + break; + case Ident_3: /* executed */ + *Enum_Ref_Par = Ident_2; + break; + case Ident_4: break; + case Ident_5: + *Enum_Ref_Par = Ident_3; + break; + } /* switch */ +} /* Proc_6 */ + + +Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) +/**********************************************/ + /* executed three times */ + /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ + /* Int_Par_Ref becomes 7 */ + /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ + /* Int_Par_Ref becomes 17 */ + /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ + /* Int_Par_Ref becomes 18 */ +One_Fifty Int_1_Par_Val; +One_Fifty Int_2_Par_Val; +One_Fifty *Int_Par_Ref; +{ + One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 2; + *Int_Par_Ref = Int_2_Par_Val + Int_Loc; +} /* Proc_7 */ + + +Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) +/*********************************************************************/ + /* executed once */ + /* Int_Par_Val_1 == 3 */ + /* Int_Par_Val_2 == 7 */ +Arr_1_Dim Arr_1_Par_Ref; +Arr_2_Dim Arr_2_Par_Ref; +int Int_1_Par_Val; +int Int_2_Par_Val; +{ + REG One_Fifty Int_Index; + REG One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 5; + Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; + Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; + Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; + for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) + Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; + Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; + Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; + Int_Glob = 5; +} /* Proc_8 */ + + +Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) +/*************************************************/ + /* executed three times */ + /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ + /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ + /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ + +Capital_Letter Ch_1_Par_Val; +Capital_Letter Ch_2_Par_Val; +{ + Capital_Letter Ch_1_Loc; + Capital_Letter Ch_2_Loc; + + Ch_1_Loc = Ch_1_Par_Val; + Ch_2_Loc = Ch_1_Loc; + if (Ch_2_Loc != Ch_2_Par_Val) + /* then, executed */ + return (Ident_1); + else /* not executed */ + { + Ch_1_Glob = Ch_1_Loc; + return (Ident_2); + } +} /* Func_1 */ + + +Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) +/*************************************************/ + /* executed once */ + /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ + /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ + +Str_30 Str_1_Par_Ref; +Str_30 Str_2_Par_Ref; +{ + REG One_Thirty Int_Loc; + Capital_Letter Ch_Loc; + + Int_Loc = 2; + while (Int_Loc <= 2) /* loop body executed once */ + if (Func_1 (Str_1_Par_Ref[Int_Loc], + Str_2_Par_Ref[Int_Loc+1]) == Ident_1) + /* then, executed */ + { + Ch_Loc = 'A'; + Int_Loc += 1; + } /* if, while */ + if (Ch_Loc >= 'W' && Ch_Loc < 'Z') + /* then, not executed */ + Int_Loc = 7; + if (Ch_Loc == 'R') + /* then, not executed */ + return (true); + else /* executed */ + { + if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) + /* then, not executed */ + { + Int_Loc += 7; + Int_Glob = Int_Loc; + return (true); + } + else /* executed */ + return (false); + } /* if Ch_Loc */ +} /* Func_2 */ + + +Boolean Func_3 (Enum_Par_Val) +/***************************/ + /* executed once */ + /* Enum_Par_Val == Ident_3 */ +Enumeration Enum_Par_Val; +{ + Enumeration Enum_Loc; + + Enum_Loc = Enum_Par_Val; + if (Enum_Loc == Ident_3) + /* then, executed */ + return (true); + else /* not executed */ + return (false); +} /* Func_3 */ + +#endif /* PASS2 */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/Makefile new file mode 100644 index 00000000000..4748287b0db --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/Makefile @@ -0,0 +1,3 @@ +install: + +clean: diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/dpsta.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/dpsta.h new file mode 100644 index 00000000000..bfc077c205a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/dpsta.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: dpsta.h 789504 2020-07-30 03:37:02Z $ + */ + +#ifndef _DPSTA_H_ +#define _DPSTA_H_ + +typedef enum { + DPSTA_MODE_PSTA = 1, + DPSTA_MODE_DWDS = 2, + DPSTA_MODE_WET = 3 +} dpsta_mode_e; + +typedef struct psta_if psta_if_t; + +/* Proxy STA instance data and exported functions */ +typedef struct psta_if_api { + void *wl; + void *psta; + void *bsscfg; + bool (*is_ds_sta)(void *wl, void *psta, struct ether_addr *ea); + void *(*psta_find)(void *wl, void *psta, uint8 *ea); + bool (*bss_auth)(void *wl, void *bsscfg); + dpsta_mode_e mode; +} psta_if_api_t; + +extern psta_if_t *dpsta_register(uint32 unit, psta_if_api_t *inst); +extern int32 dpsta_unregister(uint32 unit); +extern int32 dpsta_recv(void *p); +extern void dpsta_flush_stalist(void); + +#endif /* _DPSTA_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/dpsta_linux.h b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/dpsta_linux.h new file mode 100644 index 00000000000..c40795b86ac --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/dpsta_linux.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022, Broadcom. All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * <> + * + * $Id: dpsta_linux.h 773108 2019-03-13 07:14:59Z $ + */ + +#ifndef _DPSTA_LINUX_H_ +#define _DPSTA_LINUX_H_ + +#define DPSTA_CMD_ENABLE SIOCDEVPRIVATE + +/* dpsta msglevel */ +#define DPSTA_ERROR_VAL 0x00000001 +#define DPSTA_TRACE_VAL 0x00000002 +#define DPSTA_PKT_VAL 0x00000004 + +/* upstream policy for wireless client */ +enum dpsta_policy { + DPSTA_POLICY_AUTO = 0, /* If same radio is not connected, go to cross radio */ + DPSTA_POLICY_SAMEBAND, /* Force to same radio */ + DPSTA_POLICY_CROSSBAND, /* Force to cross radio */ + DPSTA_POLICY_AUTO_0, /* If radio-0 is not connected, go to radio-1 */ + DPSTA_POLICY_AUTO_1, /* If radio-1 is not connected, go to radio-0 */ + DPSTA_POLICY_LAST +}; + +/* upstream policy for wired client (host/ethernet) */ +enum dpsta_lan_uif { + DPSTA_LAN_UIF_AUTO_0 = 0, /* If both upstream radios are connnected, prefer radio-0 */ + DPSTA_LAN_UIF_0, /* Use radio-0 as UIF for LAN traffic */ + DPSTA_LAN_UIF_1, /* Use radio-1 as UIF for LAN traffic */ + DPSTA_LAN_UIF_AUTO_1, /* If both upstream radios are connnected, prefer radio-1 */ + DPSTA_LAN_UIF_LAST +}; + +#define DPSTA_MAX_UPSTREAM_IF 3 /* Total number of wifi radios that could be used for upstream */ +#define DPSTA_USED_UPSTREAM_IF 2 /* Only use two upstreams even we have more than two radios */ + +typedef struct dpsta_enable_info { + bool enable; /* Enable/Disable Dualband PSTA mode */ + uint32 policy; /* Inband or crossband repeating */ + uint32 lan_uif; /* Upstream interface for lan traffic */ + /* Upstream interfaces managed by DPSTA */ + uint8 upstream_if[DPSTA_MAX_UPSTREAM_IF][IFNAMSIZ]; +} dpsta_enable_info_t; + +typedef struct dpsta_cnt_s { + uint32 tx[DPSTA_MAX_UPSTREAM_IF]; /**< tx data for wired/host clients */ + uint32 wtx[DPSTA_MAX_UPSTREAM_IF]; /**< tx data for wireless clients */ + uint32 rx; /**< dpsta rx data */ +} dpsta_cnt_t; +#endif /* _DPSTA_LINUX_H_ */ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/linux.4908/dpsta.o b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/linux.4908/dpsta.o new file mode 100644 index 00000000000..e69de29bb2d diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/linux/dpsta.o b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dpsta/linux/dpsta.o new file mode 100644 index 00000000000..e69de29bb2d diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/Makefile new file mode 100644 index 00000000000..26354fe50e1 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/Makefile @@ -0,0 +1,13 @@ + +EXE = dsldiagd + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/Makefile.fullsrc new file mode 100644 index 00000000000..a1f5fb1cbec --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/Makefile.fullsrc @@ -0,0 +1,146 @@ +# +# In most cases, you only need to modify this first section. +# +EXE = dsldiagd +OBJS = dsldiagd.o adslctlapi.o DiagSock.o + +PACKAGE_NAME = dsldiagd +BEEPPKG_INFO = $(PACKAGE_NAME)$(BEEP_PKT_INFO_SUFIX) +BEEP_TAR_GZ = $(BEEP_TAR_GZ_PREFIX)$(PACKAGE_NAME)$(BEEP_TAR_GZ_SUFIX) +BEEP_MANIFEST_SUFIX=.manifest +BEEPPKG_MANIFEST=$(PACKAGE_NAME)$(BEEP_MANIFEST_SUFIX) +EEDIRS = $(sort $(dir $(wildcard */))) + +all dynamic install: conditional_build + +# +# Set our CommEngine directory (by splitting the pwd into two words +# at /userspace and taking the first word only). +# Then include the common defines under CommEngine. +# +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) + +include $(BUILD_DIR)/make.common + +ifeq ($(strip $(PROFILE_ARCH)),aarch64) +LIBDIR_NAME = lib64 +else +LIBDIR_NAME = lib +endif + +LIBS = -lxdslctl + +# when build for module software, don't link to cms libs +ifneq ($(strip $(BUILD_BRCM_CMS)),) +ifneq ($(strip $(CMS_ACTION_LOG)),) +#ifeq ($(strip $(BUILD_BEEP_DSLDIAGD)),) +LIBS += -lcms_msg $(CMS_COMMON_LIBS) +#endif +endif +endif + +clean: generic_clean + rm -f $(INSTALL_DIR)/bin/$(EXE) + rm -f $(USERSPACE_DL_MODULES_BEEP_DIR)/$(BEEP_TAR_GZ_PREFIX)*$(PACKAGE_NAME)*$(BEEP_TAR_GZ_SUFIX) $(USERSPACE_DL_MODULES_BEEP_DIR)/Packages + +binaryonly_dist_clean: clean generic_binaryonly_dist_clean + rm -f Makefile.fullsrc + + +ifneq ($(strip $(BUILD_BEEP_DSLDIAGD)),) +conditional_build: $(BEEP_TAR_GZ) +else +ifneq ($(strip $(BUILD_DSLDIAGD)),) +conditional_build: $(EXE) generic_exe_install +else +conditional_build: + @echo "skipping dsldiagd (not configured)" +endif +endif + +$(BEEP_TAR_GZ): $(EXE) + mkdir -p ./pkg/bin + mkdir -p ./pkg/lib + mkdir -p ./pkg/$(LIBDIR_NAME) + ln -sf busybox route + mv route ./pkg/bin + install -m 755 $(EXE) ./pkg/bin + $(STRIP) ./pkg/bin/$(EXE) + cp -f $(INSTALL_DIR)/lib/libxdslctl.so ./pkg/$(LIBDIR_NAME) + tar zcf $(EXE)$(BEEP_TAR_GZ_SUFIX) -C ./pkg . + rm -rf ./pkg + mkdir -p $(USERSPACE_DL_MODULES_BEEP_DIR) + + for d in ${EEDIRS}; do \ + #echo "Working on ee dir $$d ...";\ + if [ -a $$d/$(BEEPPKG_INFO) ]; then \ + echo "pkginfo.txt file: $$d/$(BEEPPKG_INFO)";\ + if [ -a $$d/$(BEEPPKG_MANIFEST) ]; then \ + echo "pkg manifest file: $$d/$(BEEPPKG_MANIFEST)";\ + cp -fav $$d/$(BEEPPKG_MANIFEST) .;\ + $(HOSTTOOLS_DIR)/beep/beepPkgBuilder -f $$d/$(BEEPPKG_INFO);\ + rm -f $(BEEPPKG_MANIFEST);\ + fi;\ + fi;\ + done + + mv -f $(BEEP_TAR_GZ_PREFIX)*$(PACKAGE_NAME)*$(BEEP_TAR_GZ_SUFIX) $(USERSPACE_DL_MODULES_BEEP_DIR) + rm -f $(EXE)$(BEEP_TAR_GZ_SUFIX) +# +# Private apps and libs are allowed to include header files from the +# private and public directories. +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) + + + +# +# Private apps and libs are allowed to link with libraries from the +# private and public directories. +# +# WARNING: Do not modify this section unless you understand the +# license implications of what you are doing. +# +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + + + +# ssk.c needs cms_boardioctl.h, which needs these headers +CFLAGS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) + +CFLAGS += -DSUPPORT_DSL + + +# +# Implicit rule will make the .c into a .o +# Implicit rule is $(CC) -c $(CPPFLAGS) $(CFLAGS) +# See Section 10.2 of Gnu Make manual +# +$(EXE): $(OBJS) + $(CC) -o $@ $(OBJS) $(BCM_LD_FLAGS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + + + +# +# Include the rule for making dependency files. +# The '-' in front of the second include suppresses +# error messages when make cannot find the .d files. +# It will just regenerate them. +# See Section 4.14 of Gnu Make. +# + +include $(BUILD_DIR)/make.deprules + +-include $(OBJS:.o=.d) + + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/autodetect new file mode 100644 index 00000000000..dce5c7785f2 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/dsldiagd/autodetect @@ -0,0 +1,3 @@ +dependson: private/libs/xdslctl public/libs/cms_msg public/libs/cms_util public/libs/bcm_flashutil public/libs/bcm_boardctl +condition: ifneq ($(or $(strip $(BUILD_DSLDIAGD)),$(strip $(BUILD_BEEP_DSLDIAGD))),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/eapd/linux/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/eapd/linux/Makefile new file mode 100644 index 00000000000..52c4b255a47 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/eapd/linux/Makefile @@ -0,0 +1,169 @@ +#Linux Makefile + +include ../../.config + +INCLUDE += -I. -I.. -I$(SRCBASE)/include ${WLAN_StdIncPathA} -I$(SRCBASE)/../components/shared -I$(SRCBASE)/../components/wlioctl/include -I$(SRCBASE)/../components/proto/include -I$(SRCBASE)/common/include -I$(TOP)/shared -I../../shared -I../../nas${BCMEX}$(EX7) -I../../nas${BCMEX}$(EX7)/nas_fbt +INCLUDE += -I$(SRCBASE)/shared/bcmwifi/include -I$(SRCBASE)/../components/bcmcrypto/include -I$(TOP_PLATFORM)/nas${BCMEX}$(EX7)/nas + +ifneq ($(CMWIFI),) +INCLUDE += -I$(SRCBASE)/shared/bcmwifi/include +endif + +CFLAGS += $(INCLUDE) +CFLAGS += $(WLAN_ComponentIncPathA) +CFLAGS += -DEAPD_WKSP_AUTO_CONFIG +CFLAGS += -I$(HND_SRC)/router-sysdep/eapd/ + +ifneq ($(CMWIFI),) +ifneq ($(BUILD_PASSPOINT_R2),) +CFLAGS += -DNAS_GTK_PER_STA +endif +endif + +#CFLAGS += -DNAS_GTK_PER_STA +CFLAGS += -Wall -DEAPDDUMP + +CFLAGS += -s + +ifneq ($(LINUXDIR),) +CFLAGS += -Dlinux +endif + +# trunk uses bcmcrypto component +CFLAGS += -DBCMCRYPTO_COMPONENT + +ifneq ($(CMWIFI),) +CFLAGS += -DBCM_NETXL +ifneq ($(DSLCPE_WLCSM_EXT),) +LDFLAGS+=-lwlcsm +endif +endif +LDFLAGS += -L$(TOP_PLATFORM)/nvram$(BCMEX)$(EX7) -L$(INSTALLDIR)/nvram/usr/lib -lnvram ${EXTRA_NV_LDFLAGS} +LDFLAGS += -L$(TOP)/shared -L$(INSTALLDIR)/shared/usr/lib -lshared -lpthread +LDFLAGS += $(EXTRA_LDFLAGS) + +vpath %.c $(TOP_PLATFORM)/eapd${BCMEX}$(EX7) $(TOP)/shared + +OBJS = eapd.o eapd_linux.o +OBJS += nas_eap.o wps_eap.o + +#ifdef BCMWAPI_WAI +ifeq ($(CONFIG_WAPI),y) +OBJS += wai_eap.o +endif +#endif + +#ifdef BCM_CUSTOM_EVENT +ifeq ($(CONFIG_BCM_CUSTOM_EVENT),y) +OBJS += custom_eventd_eap.o +CFLAGS += -DBCM_CUSTOM_EVENT +endif +#endif + +#ifdef BCM_DCS +ifeq ($(RTCONFIG_BCMDCS),y) +OBJS += dcs_eap.o +CFLAGS += -DBCM_DCS +endif +#endif + +#ifdef BCM_MEVENT +ifeq ($(CONFIG_BCM_MEVENT),y) +OBJS += mevent_eap.o +CFLAGS += -DBCM_MEVENT +endif +#endif + +#ifdef BCM_BSD +ifeq ($(RTCONFIG_BCMBSD),y) +OBJS += bsd_eap.o +CFLAGS += -DBCM_BSD +endif +#endif + +#ifdef BCM_DRSDBD +ifeq ($(RTCONFIG_BCMDRSDBD),y) +OBJS += drsdbd_eap.o +CFLAGS += -DBCM_DRSDBD +endif +#endif + +#ifdef BCM_SSD +ifeq ($(RTCONFIG_BCMSSD),y) +OBJS += ssd_eap.o +CFLAGS += -DBCM_SSD +endif +#endif + +#ifdef BCM_EVENTD +ifeq ($(or $(RTCONFIG_BCMEVENTD),$(RTCONFIG_BCN_RPT)),y) +OBJS += eventd_eap.o +CFLAGS += -DBCM_EVENTD +endif +#endif + +ifneq ($(BCM_ECBD),) +OBJS += ecbd_eap.o +CFLAGS += -DBCM_ECBD +endif + +#ifdef BCM_ASPMD +ifneq (2_6,$(LINUX_VERSION)) +ifeq ($(CONFIG_BCMASPMD),y) +OBJS += aspm_eap.o +CFLAGS += -DBCM_ASPMD +endif +endif +#endif + +#ifdef CONFIG_VISUALIZATION +ifeq ($(RTCONFIG_VISUALIZATION),y) +OBJS += visdcoll_eap.o +endif +#endif + +#ifdef BCM_CEVENT +ifeq ($(CONFIG_BCM_CEVENT),y) +OBJS += cevent_eap.o +CFLAGS += -DBCM_CEVENT +endif +#endif + +OBJS += rgd_eap.o +CFLAGS += -DBCM_RGD + +#ifdef BCM_WBD +ifeq ($(CONFIG_WBD),y) +OBJS += wbd_eap.o +endif +#endif + +OBJS += wlevent_eap.o +CFLAGS += -DBCM_WLEVENT + +OBJS += wlceventd_eap.o +CFLAGS += -DBCM_WLCEVENTD + +all: eapd + +ifneq ($(PREBUILT_BCMBIN),1) +ifneq ($(wildcard ./prebuilt/eapd),) +eapd: + cp ./prebuilt/eapd . +else +eapd: $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) +endif +else +eapd: + cp -f $(TOP_PLATFORM)/$(shell pwd | sed 's/\(.*router-sysdep\/\)//')/$(PRBM_DIR)/$@ ./ +endif + + +install: all + install -d $(INSTALLDIR)/bin + install eapd $(INSTALLDIR)/bin + $(STRIP) $(INSTALLDIR)/bin/eapd + +clean: + rm -f *.o eapd diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/eapd/linux/prebuilt/eapd b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/eapd/linux/prebuilt/eapd new file mode 100755 index 00000000000..b830910087a Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/eapd/linux/prebuilt/eapd differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/emfconf/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/emfconf/Makefile new file mode 100644 index 00000000000..4c9124269b3 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/emfconf/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2022, Broadcom. All Rights Reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# +# <> +# +# $Id: Makefile 802428 2021-08-26 09:29:53Z $ +# + +CROSS = +CC = $(CROSS)gcc +AR = $(CROSS)ar +STRIP = $(CROSS)strip + +ALL_OBJS = emfu.o emfu_linux.o + +CCFLAGS = -Os -Wall -I$(SRCBASE)/include ${WLAN_StdIncPathA} ${WLAN_ComponentIncPathA} -I$(SRCBASE)/common/include -I$(SRCBASE_ROUTER)/shared -I$(SRCBASE)/../components/router/shared/ -I$(HND_SRC)/router-sysdep/bcmdrv/include/emf/emf/ + +CCFLAGS += $(USR_CFLAGS) + +ifneq ($(wildcard ./prebuilt),) +all: + -cp prebuilt/emf emf +else +all: emf +endif + +emf: $(ALL_OBJS) + $(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $(ALL_OBJS) $(LDLIBS) + $(STRIP) $@ + +$(ALL_OBJS): %.o: %.c + @echo " " + @echo "Making $<" + $(CC) $(CCFLAGS) -c $< + +install: all + install -d $(INSTALLDIR)/emf/usr/sbin + install -m 755 emf $(INSTALLDIR)/emf/usr/sbin + +.PHONY: clean +clean: + -rm -f *.o *~ core emf diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/emfconf/prebuilt/emf b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/emfconf/prebuilt/emf new file mode 100755 index 00000000000..d108156cf43 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/emfconf/prebuilt/emf differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/igsconf/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/igsconf/Makefile new file mode 100644 index 00000000000..c1479ddc219 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/igsconf/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2022, Broadcom. All Rights Reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# +# <> +# +# $Id: Makefile 775415 2019-05-29 18:14:36Z $ +# + +CROSS = +CC = $(CROSS)gcc +AR = $(CROSS)ar +STRIP = $(CROSS)strip + +ALL_OBJS = igsu.o igsu_linux.o + +CCFLAGS = -Os -Wall -I$(SRCBASE)/include ${WLAN_StdIncPathA} ${WLAN_ComponentIncPathA} -I$(SRCBASE)/common/include -I$(SRCBASE_ROUTER)/shared -I$(HND_SRC)/router-sysdep/bcmdrv/include/emf/igs/ + +CCFLAGS += $(USR_CFLAGS) + +ifneq ($(wildcard ./prebuilt),) +all: + -cp prebuilt/igs igs +else +all: igs +endif + +igs: $(ALL_OBJS) + $(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $(ALL_OBJS) $(LDLIBS) + $(STRIP) $@ + +$(ALL_OBJS): %.o: %.c + @echo " " + @echo "Making $<" + $(CC) $(CCFLAGS) -c $< + +install: all + install -d $(INSTALLDIR)/igs/usr/sbin + install -m 755 igs $(INSTALLDIR)/igs/usr/sbin + +.PHONY: clean +clean: + -rm -f *.o *~ core igs diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/igsconf/prebuilt/igs b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/igsconf/prebuilt/igs new file mode 100755 index 00000000000..1ed090eebab Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/emf/igsconf/prebuilt/igs differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/Makefile new file mode 100644 index 00000000000..5ec2d9b49db --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/Makefile @@ -0,0 +1,10 @@ +install: + +clean: + +EXE: envram envrams + +all: $(EXE) + +$(EXE): + cp -f $(TOP_PLATFORM)/$(shell pwd | sed 's/\(.*router-sysdep\/\)//')/envram/$@ ./ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-47622-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-47622-arm new file mode 100755 index 00000000000..85c4686b617 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-47622-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-4908-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-4908-arm new file mode 100755 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-4908-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-4912-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-4912-arm new file mode 100644 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-4912-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63138-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63138-arm new file mode 100755 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63138-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63146-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63146-arm new file mode 100644 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63146-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63158-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63158-arm new file mode 100644 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63158-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63178-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63178-arm new file mode 100755 index 00000000000..85c4686b617 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-63178-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6756-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6756-arm new file mode 100644 index 00000000000..85c4686b617 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6756-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6846-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6846-arm new file mode 100644 index 00000000000..85c4686b617 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6846-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6855-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6855-arm new file mode 100644 index 00000000000..85c4686b617 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6855-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6856-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6856-arm new file mode 100644 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6856-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6858-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6858-arm new file mode 100644 index 00000000000..be6f9ee6054 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envram_saved-6858-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-47622-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-47622-arm new file mode 100755 index 00000000000..9bbe46dcb18 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-47622-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-4908-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-4908-arm new file mode 100755 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-4908-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-4912-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-4912-arm new file mode 100644 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-4912-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63138-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63138-arm new file mode 100755 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63138-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63146-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63146-arm new file mode 100644 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63146-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63158-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63158-arm new file mode 100644 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63158-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63178-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63178-arm new file mode 100755 index 00000000000..9bbe46dcb18 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-63178-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6756-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6756-arm new file mode 100644 index 00000000000..9bbe46dcb18 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6756-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6846-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6846-arm new file mode 100644 index 00000000000..9bbe46dcb18 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6846-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6855-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6855-arm new file mode 100644 index 00000000000..9bbe46dcb18 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6855-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6856-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6856-arm new file mode 100644 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6856-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6858-arm b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6858-arm new file mode 100644 index 00000000000..ddc1740480f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/envram_bin/envram/envrams_saved-6858-arm differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Bcmbuild.mk new file mode 100644 index 00000000000..1ed6184373b --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Bcmbuild.mk @@ -0,0 +1,67 @@ +EXE := ethctl + +default dynamic: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + + +ARCH := $(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/bin +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(BRCMDRIVERS_DIR)/opensource/phy + +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR +export BRCM_CHIP + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin + + +all install: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + + + +clean: clean_legacy + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Makefile new file mode 100644 index 00000000000..f8b47ea1cc4 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Makefile @@ -0,0 +1,13 @@ + +EXE = ethctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Makefile.fullsrc new file mode 100644 index 00000000000..96224bb9b8e --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/Makefile.fullsrc @@ -0,0 +1,25 @@ +OBJS := ethctl.o ethctl_cmd.o + +LIBS := -L$(HND_SRC)/router-sysdep/ethctl_lib/ -lethctl + +#CFLAGS += -Werror -Wfatal-errors + +CFLAGS += -DCONFIG_BCM9$(BRCM_CHIP) + +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + +# force ethctl_cmd to be built every time for the build date and time. +ethctl_cmd.o: FORCE + +.PHONY: FORCE + +binaryonly_prepare: + -cp $(EXE) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ -I$(HND_SRC)/bcmdrivers/opensource/phy/ +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/autodetect new file mode 100644 index 00000000000..40ded167976 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/autodetect @@ -0,0 +1,3 @@ +dependson: private/libs/ethctl +makeflags: dynamic + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/prebuilt/ethctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/prebuilt/ethctl new file mode 100755 index 00000000000..4febd0228e9 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl/prebuilt/ethctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Bcmbuild.mk new file mode 100644 index 00000000000..adbb665934b --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Bcmbuild.mk @@ -0,0 +1,60 @@ +LIB := libethctl.so + +default: all + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH := $(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(BRCMDRIVERS_DIR)/opensource/phy +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + + +all install: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Makefile new file mode 100644 index 00000000000..0051b620e04 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Makefile @@ -0,0 +1,13 @@ + +LIB = libethctl.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Makefile.fullsrc new file mode 100644 index 00000000000..51c3ba0e327 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/Makefile.fullsrc @@ -0,0 +1,34 @@ +OBJS := ethctl_api.o sha256.o + +#CFLAGS += -Werror -Wfatal-errors + +CFLAGS += -DCONFIG_BCM9$(BRCM_CHIP) + +# These are public API headers needed by other apps which want to call this lib. +# Private/internal headers should not be listed here. +HEADERS := + +# from Bcmbuild.mk +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include + +all: $(LIB) + mkdir -p $(HEADER_INSTALL_DIR) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive + + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(addprefix $(HEADER_INSTALL_DIR)/,$(HEADERS)) + +binaryonly_prepare: + -cp $(LIB) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ -I$(HND_SRC)/bcmdrivers/opensource/phy/ +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/autodetect new file mode 100755 index 00000000000..8b137891791 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/autodetect @@ -0,0 +1 @@ + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/prebuilt/libethctl.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/prebuilt/libethctl.so new file mode 100755 index 00000000000..2737537e8f7 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethctl_lib/prebuilt/libethctl.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Bcmbuild.mk new file mode 100644 index 00000000000..eeb943e9342 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Bcmbuild.mk @@ -0,0 +1,73 @@ +EXE := ethswctl + +all dynamic install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + + +ARCH := $(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/bin +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR +export BRCM_CHIP + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin + + +ifneq ($(strip $(BUILD_ETHSWCTL)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + +else + +conditional_build: + @echo "Skipping $(EXE) (not configured)" + +endif + + +clean: clean_legacy + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Makefile new file mode 100644 index 00000000000..6e1472ca3cc --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Makefile @@ -0,0 +1,13 @@ + +EXE = ethswctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Makefile.fullsrc new file mode 100644 index 00000000000..cda14fca515 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/Makefile.fullsrc @@ -0,0 +1,24 @@ +OBJS := ethswctl.o + +LIBS := -L$(HND_SRC)/router-sysdep/ethswctl_lib/ -lethswctl + +#CFLAGS += -Werror -Wfatal-errors +CFLAGS += -Wfatal-errors + +ifeq ($(findstring _$(strip $(BRCM_CHIP))_,_63138_4908_63158_63178_),_$(strip $(BRCM_CHIP))_) +CFLAGS += -DACB_ALGORITHM2 +endif + +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + + +binaryonly_prepare: + -cp $(EXE) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/autodetect new file mode 100644 index 00000000000..e07842122b4 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/autodetect @@ -0,0 +1,3 @@ +dependson: private/libs/ethswctl public/libs/bcm_flashutil public/libs/bcm_util +condition: ifneq ($(strip $(BUILD_ETHSWCTL)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/prebuilt/ethswctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/prebuilt/ethswctl new file mode 100755 index 00000000000..d71a89e0d56 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl/prebuilt/ethswctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Bcmbuild.mk new file mode 100644 index 00000000000..08446d5db44 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Bcmbuild.mk @@ -0,0 +1,69 @@ +LIB := libethswctl.so + +all dynamic install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH := $(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib + + +ifneq ($(strip $(BUILD_ETHSWCTL)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + +else + +conditional_build: + @echo "Skipping $(LIB) (not configured)" + +endif + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Makefile new file mode 100644 index 00000000000..55094b930e5 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Makefile @@ -0,0 +1,13 @@ + +LIB = libethswctl.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Makefile.fullsrc new file mode 100644 index 00000000000..9f5a50f1a28 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/Makefile.fullsrc @@ -0,0 +1,32 @@ +OBJS := ethswctl_api.o + +#CFLAGS += -Werror -Wfatal-errors + +# These are public API headers needed by other apps which want to call this lib. +# Private/internal headers should not be listed here. +HEADERS := + +# from Bcmbuild.mk +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include + +all: $(LIB) + mkdir -p $(HEADER_INSTALL_DIR) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive + + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(addprefix $(HEADER_INSTALL_DIR)/,$(HEADERS)) + +binaryonly_prepare: + -cp $(LIB) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/autodetect new file mode 100644 index 00000000000..ecaa99f0f1d --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/autodetect @@ -0,0 +1,3 @@ + +condition: ifneq ($(strip $(BUILD_ETHSWCTL)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/prebuilt/libethswctl.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/prebuilt/libethswctl.so new file mode 100755 index 00000000000..806974eb5a6 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/ethswctl_lib/prebuilt/libethswctl.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Bcmbuild.mk new file mode 100644 index 00000000000..3100c463020 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Bcmbuild.mk @@ -0,0 +1,72 @@ +EXE := fcctl +EXEALT := fc + +all dynamic install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + + +ARCH := $(PROFILE_ARCH) +EXE_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/bin +ALLOWED_INCLUDE_PATHS := -I. \ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PRIV_PATH)/$(BRCM_BOARD) + +ALLOWED_LIB_DIRS := /lib:/lib/private:/lib/public + +export ARCH CFLAGS BCM_LD_FLAGS CMS_LIB_PATH CMS_LIB_RPATH EXE_INSTALL_DIR +# export TOOLCHAIN_PREFIX + + + +# Final location of EXE for system image. Only the BRCM build system needs to +# know about this. +FINAL_EXE_INSTALL_DIR := $(INSTALL_DIR)/bin + + +ifneq ($(strip $(BUILD_FCCTL)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_EXE_INSTALL_DIR) + cp -p $(EXE_INSTALL_DIR)/$(EXE) $(FINAL_EXE_INSTALL_DIR) + (cd $(FINAL_EXE_INSTALL_DIR); ln -sf $(EXE) $(EXEALT)) + +else + +conditional_build: + @echo "Skipping $(EXE) (not configured)" + +endif + + +clean: + rm -f $(FINAL_EXE_INSTALL_DIR)/$(EXE) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Makefile new file mode 100644 index 00000000000..071c94f9d76 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Makefile @@ -0,0 +1,15 @@ + +EXE = fcctl + +all: + @cp -f prebuilt/$(EXE) . + +install: generic_exe_install + mkdir -p $(INSTALL_DIR)/bin + (cd $(INSTALL_DIR)/bin; rm -f fc; ln -s $(EXE) fc) + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Makefile.fullsrc new file mode 100644 index 00000000000..bf480efe24f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/Makefile.fullsrc @@ -0,0 +1,20 @@ +OBJS := fcctl.o fcctl_cmds.o + +LIBS := -L$(HND_SRC)/router-sysdep/fcctl_lib/ -lfcctl + +#CFLAGS += -Werror -Wfatal-errors +CFLAGS += -Wfatal-errors + +$(EXE): $(OBJS) + $(CC) $(BCM_LD_FLAGS) -o $@ $(OBJS) -Wl,-rpath,$(CMS_LIB_RPATH) $(CMS_LIB_PATH) $(LIBS) + + +binaryonly_prepare: + -cp $(EXE) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/userspace/private/include/ -I$(HND_SRC)/bcmdrivers/broadcom/include/bcm963xx/ +-include $(OBJS:.o=.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/autodetect new file mode 100644 index 00000000000..181efa51830 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/autodetect @@ -0,0 +1,5 @@ + +dependson: private/libs/fcctl +condition: ifneq ($(strip $(BUILD_FCCTL)),) +makeflags: $(BUILD_FCCTL) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/prebuilt/fcctl b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/prebuilt/fcctl new file mode 100755 index 00000000000..619de3d5658 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl/prebuilt/fcctl differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Bcmbuild.mk new file mode 100644 index 00000000000..74490f1c170 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Bcmbuild.mk @@ -0,0 +1,69 @@ +LIB := libfcctl.so + +all dynamic install: conditional_build + + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + + +ARCH := $(PROFILE_ARCH) +LIB_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/lib +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include +ALLOWED_INCLUDE_PATHS := -I.\ + -I$(BUILD_DIR)/userspace/public/include \ + -I$(BUILD_DIR)/userspace/public/include/$(OALDIR) \ + -I$(BUILD_DIR)/userspace/private/include \ + -I$(BUILD_DIR)/userspace/private/include/$(OALDIR) \ + -I$(INC_BRCMDRIVER_PRIV_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) \ + -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) + +export ARCH CFLAGS LIB_INSTALL_DIR HEADER_INSTALL_DIR + + +# Final location of LIB for system image. Only the BRCM build system needs to +# know about this. +FINAL_LIB_INSTALL_DIR := $(INSTALL_DIR)/lib + + +ifneq ($(strip $(BUILD_FCCTL)),) + +conditional_build: + mkdir -p objs + $(MAKE) -C objs -f ../Makefile install + mkdir -p $(FINAL_LIB_INSTALL_DIR) + cp -p $(LIB_INSTALL_DIR)/$(LIB) $(FINAL_LIB_INSTALL_DIR) + +else + +conditional_build: + @echo "Skipping $(LIB) (not configured)" + +endif + + +clean: clean_legacy + rm -f $(FINAL_LIB_INSTALL_DIR)/$(LIB) + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile clean + rm -rf objs + +# delete objects left over from old Makefile. (Not needed for new directory +# which started with split makefiles.) +clean_legacy: + rm -f *.o *.d $(LIB) + +CONSUMER_RELEASE_BINARYONLY_PREPARE: binaryonly_prepare + +binaryonly_prepare: + -mkdir -p objs + -$(MAKE) -C objs -f ../Makefile binaryonly_prepare + rm -rf objs + + +shell: + @echo "Entering makefile debug shell (type exit to exit) >>>" + @bash -i + @echo "exiting debug shell." diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Makefile b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Makefile new file mode 100644 index 00000000000..e2432bc246a --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Makefile @@ -0,0 +1,13 @@ + +LIB = libfcctl.so + +all: + @cp -f prebuilt/$(LIB) . + +install: generic_private_lib_install + +clean: + +dynamic: all install + +include $(BUILD_DIR)/make.common diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Makefile.fullsrc b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Makefile.fullsrc new file mode 100644 index 00000000000..a342f4150a5 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/Makefile.fullsrc @@ -0,0 +1,32 @@ +OBJS := fcctl.o + +#CFLAGS += -Werror -Wfatal-errors + +# These are public API headers needed by other apps which want to call this lib. +# Private/internal headers should not be listed here. +HEADERS := + +# from Bcmbuild.mk +HEADER_INSTALL_DIR := $(BCM_FSBUILD_DIR)/private/include + +all: $(LIB) + mkdir -p $(HEADER_INSTALL_DIR) + +$(LIB): $(OBJS) + $(CC) -shared $(BCM_LD_FLAGS) -Wl,--whole-archive,-soname,$(notdir $@) -o $@ $(OBJS) -Wl,--no-whole-archive + + +clean: + rm -f *.o *.d $(LIB) + rm -f $(LIB_INSTALL_DIR)/$(LIB) + rm -f $(addprefix $(HEADER_INSTALL_DIR)/,$(HEADERS)) + +binaryonly_prepare: + -cp $(LIB) $(mdir)/$(SAVED) + -$(MAKE) -f $(name) clean + rm -f $(mdir)/*.c $(mdir)/*.h $(mdir)/Makefile.fullsrc + + +# Generate and use dependencies. +CFLAGS += -MD -I$(HND_SRC)/bcmdrivers/broadcom/include/bcm963xx/ -I$(HND_SRC)/userspace/private/include/ +-include $(OBJS:%.o=%.d) diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/autodetect b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/autodetect new file mode 100644 index 00000000000..8679cc4654e --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/autodetect @@ -0,0 +1,3 @@ + +condition: ifneq ($(strip $(BUILD_FCCTL)),) + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/prebuilt/libfcctl.so b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/prebuilt/libfcctl.so new file mode 100755 index 00000000000..358b42b4ff9 Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fcctl_lib/prebuilt/libfcctl.so differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/Bcmbuild.mk b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/Bcmbuild.mk new file mode 100644 index 00000000000..e5602f7413f --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/Bcmbuild.mk @@ -0,0 +1,48 @@ + +libfdt: conditional_build +libfdt_src_name := dtc-1.5.1 + +# BRCM_SUPPORTS_MULTIARCH_BUILD + +CURR_DIR := $(shell pwd) +BUILD_DIR:=$(HND_SRC) +include $(BUILD_DIR)/make.common + +ifeq ($(strip $(DESKTOP_LINUX)),y) +EXTRA_CFLAGS := $(BCM_LD_FLAGS) +LDFLAGS := $(BCM_LD_FLAGS) +export EXTRA_CFLAGS LDFLAGS +endif +export LINUX_VER_STR TOOLCHAIN_PREFIX + +conditional_build: all +check_untar: + if [ ! -e $(libfdt_src_name)/Makefile ]; then \ + echo "Untarring original $(libfdt_src_name) source"; \ + unzip $(libfdt_src_name).zip; \ + touch $(libfdt_src_name)/Makefile; \ + fi; \ + +all: check_untar + mkdir -p $(INSTALL_DIR)/lib/public/ + (export PKG_CONFIG_LIBDIR=$(BCM_FSBUILD_DIR)/public/lib:$(BCM_FSBUILD_DIR)/gpl/lib; \ + export PKG_CONFIG_PATH=$(BCM_FSBUILD_DIR)/public/lib/pkgconfig:$(BCM_FSBUILD_DIR)/gpl/lib/pkgconfig; \ + cd $(libfdt_src_name); \ + make NO_PYTHON=1 libfdt HOME=$(BCM_FSBUILD_DIR)/public/; \ + make NO_PYTHON=1 libfdt HOME=$(BCM_FSBUILD_DIR)/public/ INSTALL="$(INSTALL)" install-lib ; \ + make NO_PYTHON=1 libfdt HOME=$(BCM_FSBUILD_DIR)/public/ INSTALL="$(INSTALL)" install-includes; ) + mkdir -p $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + cp -d $(BCM_FSBUILD_DIR)/public/lib/libfdt*.so* $(INSTALL_DIR)/lib$(BCM_INSTALL_SUFFIX_DIR) + +clean: + rm -f $(INSTALL_DIR)/lib/public/libfdt.so* + -[ ! -e objs/$(PROFILE_ARCH)/Makefile ] || make objs/$(PROFILE_ARCH) uninstall + cd $(libfdt_src_name); make clean + +bcm_dorel_distclean: distclean + +distclean: clean + +shell: + bash -i + diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1.zip b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1.zip new file mode 100644 index 00000000000..5c8fbfac80f Binary files /dev/null and b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1.zip differ diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/.travis.yml b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/.travis.yml new file mode 100644 index 00000000000..114932a23cc --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/.travis.yml @@ -0,0 +1,33 @@ +language: c + +# Coverity Scan uploads +env: + global: + # COVERITY_SCAN_TOKEN (dgibson/dtc) + - secure: "vlHvXe618//IM9LQaKzqsrUbjs7ng0L9UCST4kJbJnFQDXvVe5JiSmJGd4ef7mm0NUv5bMRl2W3xCiu6BYAu/NvU3tMNHoLG+JgCJs0+wLJXbWOwji/NmH7olqgJG+CmpaCMXjARF6+nrTnBYHJL6cYyf4KVoV4B0I/hLUW91+s=" + +matrix: + include: + - addons: + apt: + packages: + - swig + - python-dev + - valgrind + - libyaml-0-2 + coverity_scan: + project: + name: dtc + description: Device Tree Compiler + notification_email: david@gibson.dropbear.id.au + build_command: make + branch_pattern: coverity_scan + script: + - make + - make check && make checkm + + # Check it builds properly without optional packages: + # python, valgrind, libyaml + - script: + - make + - make check diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/BSD-2-Clause b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/BSD-2-Clause new file mode 100644 index 00000000000..da366e2ce50 --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/BSD-2-Clause @@ -0,0 +1,32 @@ +Valid-License-Identifier: BSD-2-Clause +SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html +Usage-Guide: + To use the BSD 2-clause "Simplified" License put the following SPDX + tag/value pair into a comment according to the placement guidelines in + the licensing rules documentation: + SPDX-License-Identifier: BSD-2-Clause +License-Text: + +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/Documentation/dt-object-internal.txt b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/Documentation/dt-object-internal.txt new file mode 100644 index 00000000000..51d68ab93ac --- /dev/null +++ b/release/src-rt-5.04axhnd.675x/router-sysdep.tuf-ax3000_v2/fdt/dtc-1.5.1/Documentation/dt-object-internal.txt @@ -0,0 +1,310 @@ +Device Tree Dynamic Object format internals +------------------------------------------- + +The Device Tree for most platforms is a static representation of +the hardware capabilities. This is insufficient for platforms +that need to dynamically insert Device Tree fragments into the +live tree. + +This document explains the the Device Tree object format and +modifications made to the Device Tree compiler, which make it possible. + +1. Simplified Problem Definition +-------------------------------- + +Assume we have a platform which boots using following simplified Device Tree. + +---- foo.dts ----------------------------------------------------------------- + /* FOO platform */ + / { + compatible = "corp,foo"; + + /* shared resources */ + res: res { + }; + + /* On chip peripherals */ + ocp: ocp { + /* peripherals that are always instantiated */ + peripheral1 { ... }; + }; + }; +---- foo.dts ----------------------------------------------------------------- + +We have a number of peripherals that after probing (using some undefined method) +should result in different Device Tree configuration. + +We cannot boot with this static tree because due to the configuration of the +foo platform there exist multiple conficting peripherals DT fragments. + +So for the bar peripheral we would have this: + +---- foo+bar.dts ------------------------------------------------------------- + /* FOO platform + bar peripheral */ + / { + compatible = "corp,foo"; + + /* shared resources */ + res: res { + }; + + /* On chip peripherals */ + ocp: ocp { + /* peripherals that are always instantiated */ + peripheral1 { ... }; + + /* bar peripheral */ + bar { + compatible = "corp,bar"; + ... /* various properties and child nodes */ + }; + }; + }; +---- foo+bar.dts ------------------------------------------------------------- + +While for the baz peripheral we would have this: + +---- foo+baz.dts ------------------------------------------------------------- + /* FOO platform + baz peripheral */ + / { + compatible = "corp,foo"; + + /* shared resources */ + res: res { + /* baz resources */ + baz_res: res_baz { ... }; + }; + + /* On chip peripherals */ + ocp: ocp { + /* peripherals that are always instantiated */ + peripheral1 { ... }; + + /* baz peripheral */ + baz { + compatible = "corp,baz"; + /* reference to another point in the tree */ + ref-to-res = <&baz_res>; + ... /* various properties and child nodes */ + }; + }; + }; +---- foo+baz.dts ------------------------------------------------------------- + +We note that the baz case is more complicated, since the baz peripheral needs to +reference another node in the DT tree. + +2. Device Tree Object Format Requirements +----------------------------------------- + +Since the Device Tree is used for booting a number of very different hardware +platforms it is imperative that we tread very carefully. + +2.a) No changes to the Device Tree binary format for the base tree. We cannot +modify the tree format at all and all the information we require should be +encoded using Device Tree itself. We can add nodes that can be safely ignored +by both bootloaders and the kernel. The plugin dtbs are optionally tagged +with a different magic number in the header but otherwise they're simple +blobs. + +2.b) Changes to the DTS source format should be absolutely minimal, and should +only be needed for the DT fragment definitions, and not the base boot DT. + +2.c) An explicit option should be used to instruct DTC to generate the required +information needed for object resolution. Platforms that don't use the +dynamic object format can safely ignore it. + +2.d) Finally, DT syntax changes should be kept to a minimum. It should be +possible to express everything using the existing DT syntax. + +3. Implementation +----------------- + +The basic unit of addressing in Device Tree is the phandle. Turns out it's +relatively simple to extend the way phandles are generated and referenced +so that it's possible to dynamically convert symbolic references (labels) +to phandle values. This is a valid assumption as long as the author uses +reference syntax and does not assign phandle values manually (which might +be a problem with decompiled source files). + +We can roughly divide the operation into two steps. + +3.a) Compilation of the base board DTS file using the '-@' option +generates a valid DT blob with an added __symbols__ node at the root node, +containing a list of all nodes that are marked with a label. + +Using the foo.dts file above the following node will be generated; + +$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts +$ fdtdump foo.dtb +... +/ { + ... + res { + ... + phandle = <0x00000001>; + ... + }; + ocp { + ... + phandle = <0x00000002>; + ... + }; + __symbols__ { + res="/res"; + ocp="/ocp"; + }; +}; + +Notice that all the nodes that had a label have been recorded, and that +phandles have been generated for them. + +This blob can be used to boot the board normally, the __symbols__ node will +be safely ignored both by the bootloader and the kernel (the only loss will +be a few bytes of memory and disk space). + +We generate a __symbols__ node to record nodes that had labels in the base +tree (or subsequent loaded overlays) so that they can be matched up with +references made to them in Device Tree objects. + +3.b) The Device Tree fragments must be compiled with the same option but they +must also have a tag (/plugin/) that allows undefined references to nodes +that are not present at compilation time to be recorded so that the runtime +loader can fix them. + +So the bar peripheral's DTS format would be of the form: + +/dts-v1/; +/plugin/; /* allow undefined references and record them */ +/ { + .... /* various properties for loader use; i.e. part id etc. */ + fragment@0 { + target = <&ocp>; + __overlay__ { + /* bar peripheral */ + bar { + compatible = "corp,bar"; + ... /* various properties and child nodes */ + } + }; + }; +}; + +Note that there's a target property that specifies the location where the +contents of the overlay node will be placed, and it references the node +in the foo.dts file. + +$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts +$ fdtdump bar.dtbo +... +/ { + ... /* properties */ + fragment@0 { + target = <0xffffffff>; + __overlay__ { + bar { + compatible = "corp,bar"; + ... /* various properties and child nodes */ + } + }; + }; + __fixups__ { + ocp = "/fragment@0:target:0"; + }; +}; + +No __symbols__ node has been generated (no label in bar.dts). +Note that the target's ocp label is undefined, so the phandle +value is filled with the illegal value '0xffffffff', while a __fixups__ +node has been generated, which marks the location in the tree where +the label lookup should store the runtime phandle value of the ocp node. + +The format of the __fixups__ node entry is + +