diff --git a/.github/workflows/unix-build.yml b/.github/workflows/unix-build.yml new file mode 100644 index 0000000..8675f8b --- /dev/null +++ b/.github/workflows/unix-build.yml @@ -0,0 +1,46 @@ +name: Unix Build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + release: + types: [ published ] + +env: + artifacts: | + me7sum + ME7Check_linux + README.md + +jobs: + build: + strategy: + matrix: + os: [ 'ubuntu', 'macos'] + runs-on: ${{ matrix.os }}-latest + steps: + - uses: actions/checkout@v4 + - name: make + run: make + - name: make test + run: make test + - uses: rlespinasse/github-slug-action@v4 + if: ${{ github.event_name != 'release' }} + with: + short-length: 6 + - uses: actions/upload-artifact@v4 + if: ${{ github.event_name != 'release' }} + with: + name: me7sum-${{ env.GITHUB_SHA_SHORT }}-${{ matrix.os }} + path: ${{ env.artifacts }} + - name: Upload ${{ matrix.os }} artifact to release + if: github.event_name == 'release' && github.event.action == 'published' + run: | + ARTIFACTS="${artifacts//$'\n'/ }" + echo "Zipping ${ARTIFACTS}" + zip -qr me7sum-${{ github.ref_name }}-${{ matrix.os }}.zip ${ARTIFACTS} + gh release upload --clobber ${{ github.ref_name }} me7sum-${{ github.ref_name }}-${{ matrix.os }}.zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml new file mode 100644 index 0000000..c5bdd1b --- /dev/null +++ b/.github/workflows/windows-build.yml @@ -0,0 +1,43 @@ +name: Windows Build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + release: + types: [ published ] + +env: + artifacts: | + me7sum.exe + ME7Check.exe + README.md + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: TheMrMilchmann/setup-msvc-dev@v3 + with: + arch: x86 + - name: build + run: nmake + - uses: rlespinasse/github-slug-action@v4 + if: ${{ github.event_name != 'release' }} + with: + short-length: 6 + - uses: actions/upload-artifact@v4 + if: ${{ github.event_name != 'release' }} + with: + name: me7sum-${{ env.GITHUB_SHA_SHORT }}-win + path: ${{ env.artifacts }} + - name: Upload windows artifact to release + if: github.event_name == 'release' && github.event.action == 'published' + run: | + $env:artifacts > artifacts.txt + cmd --% /c 7z a -tzip me7sum-${{ github.ref_name }}-win.zip @artifacts.txt + gh release upload --clobber ${{ github.ref_name }} me7sum-${{ github.ref_name }}-win.zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 8483dbb..d0d0037 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,10 @@ +.*.swp +*.d *.o *.obj *.a -*.exe +*.zip me7sum +me7sum.exe +.compiler_flags +*.bin.txt diff --git a/8D0907551C.ini b/8D0907551C.ini deleted file mode 100644 index f52166f..0000000 --- a/8D0907551C.ini +++ /dev/null @@ -1,9 +0,0 @@ -[ignition] -rom_firmware_start=0x800000 - -# main rom checksum -rom_checksum_offset=0x01bfe6 -rom_checksum_final=0x07ffe0 - -# multipoint checkums -rom_checksum_block_start=0x1fc20 diff --git a/8D0907551M.ini b/8D0907551M.ini deleted file mode 100644 index 5124efc..0000000 --- a/8D0907551M.ini +++ /dev/null @@ -1,20 +0,0 @@ -[ignition] -rom_firmware_start=0x800000 - -# main rom checksums -rom_checksum_offset=0x01e75a -rom_checksum_final=0x0fffe0 - -# multipoint checksums -rom_checksum_block_start=0x1fbd2 - -# CRCs -rom_crc1_start=0x10002 -rom_crc1_end=0x13FFE -rom_crc1=0x7A866 -rom_crc2_start=0x14252 -rom_crc2_end=0x17F4E -rom_crc2=0x7A86C -rom_crc3_start=0x18192 -rom_crc3_end=0x1FBB0 -rom_crc3=0x7A872 diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..e41790a --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,25 @@ +include vars.mk + +EXE =me7sum$(EXE_EXT) +LIBS =ini +SUBDIRS =inifile + +ifneq (, $(findstring mingw, $(SYS))) +LIBS += ws2_32 +SRC += os/pgetopt.c +endif + +include makefile.common + +.PHONY: test +test: + ./test.sh + +win: force + ./build.cmd clean + ./build.cmd + +INIS=sample.ini # bins/ferrari360.ini bins/8D0907551M.ini +.PHONY: zip +zip: win + zip -j me7sum-$(GIT_VERSION).zip me7sum.exe ME7Check.exe README.md $(INIS) diff --git a/ME7Check.exe b/ME7Check.exe new file mode 100755 index 0000000..74a6ac2 Binary files /dev/null and b/ME7Check.exe differ diff --git a/ME7Check_linux b/ME7Check_linux new file mode 100755 index 0000000..98cc65c Binary files /dev/null and b/ME7Check_linux differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a8bc71 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# Synopsis +This project is under BSD open source license. Its on the most unrestrictive freeware license possible. No warranty implied or given. + +It is a tool written in C for management of Bosch ME7.1 firmware dumps. + +The latest binary releases are always available [here](https://github.com/nyetwurk/ME7Sum/releases/latest). + +# Running +To check image.bin: +``` +ME7Check image.bin +me7sum image.bin +``` + +To output corrected checksums: +``` +me7sum image.bin out.bin +``` + +**If you do not supply "out.bin", ME7Sum will only check "image.bin" for errors - it wll not make any corrections** + +Note that if me7sum cannot completely detect checksum/CRC locations correctly, it will not output a file! + +**Always use me7sum on a original version of your bin first to make sure it is compatible!** + +**Make sure to check all corrected bins with ME7Check.exe before flashing them!** + +# Known Issues +**DO NOT USE ON TUNER MODIFIED BINARIES!** + +Many tuners modify the CRC/Checksum algorithms to discourage modification of their tunes. ME7Sum most likely will not detect such modifications. + +ME7Check may detect such modifications, but there is no way for it to be 100% sure. + +Never use ME7Sum on a file that you your self did not write. + +**Some files may require ME7Sum to be run on them iteratively, [see Issue 7](https://github.com/nyetwurk/ME7Sum/issues/7).** + +If ME7Check fails on a ME7Sum fixed file after a single pass, please post or email me the file. You may be able to get all the checksums properly fixed by re-running ME7Sum on its own outputted file. + +ME7Check should not fail on RSA corrected bins. If it does, please email the binary to me or post on Nefmoto. + +DO NOT FLASH ANY BINS without a backup ECU or a way to restore a known good bin or you may be stranded! + +It should generally autodetect checksum/CRC blocks, but is known not to work on non VAG Motronic bins, eg: + +ferrari360.bin + +# Building +Under unix or cygwin, "make" should work. On debian you will need `libgmp-dev` + +Under Windows MSVSS/nmake, type "build clean" then "build" + +Under MacOS, type "brew install gmp" then "make" + +# Contributing +Feel free to contribute to the project! + +nyet's ME7Sum: +http://nefariousmotorsports.com/forum/index.php?topic=3347.0title= +https://github.com/nyetwurk/ME7Sum/ + +360trev's ME7Sum: +http://nefariousmotorsports.com/forum/index.php?topic=2993.0title= +https://github.com/360trev/ME7Sum/ diff --git a/README b/README.orig similarity index 100% rename from README rename to README.orig diff --git a/bins/006410010A0.bin b/bins/006410010A0.bin new file mode 100644 index 0000000..61ae6c5 Binary files /dev/null and b/bins/006410010A0.bin differ diff --git a/bins/022906032CS.bin b/bins/022906032CS.bin new file mode 100644 index 0000000..5fed501 Binary files /dev/null and b/bins/022906032CS.bin differ diff --git a/bins/022906032CT.bin b/bins/022906032CT.bin new file mode 100644 index 0000000..95816dd Binary files /dev/null and b/bins/022906032CT.bin differ diff --git a/bins/066906032E.bin b/bins/066906032E.bin new file mode 100644 index 0000000..8c72a68 Binary files /dev/null and b/bins/066906032E.bin differ diff --git a/bins/06A906032AR.bin b/bins/06A906032AR.bin new file mode 100644 index 0000000..e8192dd Binary files /dev/null and b/bins/06A906032AR.bin differ diff --git a/bins/06A906032CL.bin b/bins/06A906032CL.bin new file mode 100644 index 0000000..c8f1762 Binary files /dev/null and b/bins/06A906032CL.bin differ diff --git a/bins/06A906032HJ.bin b/bins/06A906032HJ.bin new file mode 100644 index 0000000..417ac75 Binary files /dev/null and b/bins/06A906032HJ.bin differ diff --git a/bins/06A906032HN.bin b/bins/06A906032HN.bin new file mode 100644 index 0000000..d061033 Binary files /dev/null and b/bins/06A906032HN.bin differ diff --git a/bins/06A906032HS.bin b/bins/06A906032HS.bin new file mode 100644 index 0000000..084a62f Binary files /dev/null and b/bins/06A906032HS.bin differ diff --git a/bins/06A906032MJ.bin b/bins/06A906032MJ.bin new file mode 100644 index 0000000..8c9bb02 Binary files /dev/null and b/bins/06A906032MJ.bin differ diff --git a/bins/06A906032T.bin b/bins/06A906032T.bin new file mode 100644 index 0000000..01eb3c1 Binary files /dev/null and b/bins/06A906032T.bin differ diff --git a/bins/06A906032TL.bin b/bins/06A906032TL.bin new file mode 100644 index 0000000..fe869bb Binary files /dev/null and b/bins/06A906032TL.bin differ diff --git a/bins/4B0906018.bin b/bins/4B0906018.bin new file mode 100644 index 0000000..78eca84 Binary files /dev/null and b/bins/4B0906018.bin differ diff --git a/bins/4B0906018AR.bin b/bins/4B0906018AR.bin new file mode 100644 index 0000000..f10c045 Binary files /dev/null and b/bins/4B0906018AR.bin differ diff --git a/bins/4B0906018CH.bin b/bins/4B0906018CH.bin new file mode 100644 index 0000000..0846df5 Binary files /dev/null and b/bins/4B0906018CH.bin differ diff --git a/bins/4B0906018DC.bin b/bins/4B0906018DC.bin new file mode 100644 index 0000000..61f8d44 Binary files /dev/null and b/bins/4B0906018DC.bin differ diff --git a/bins/4B0906018DH.bin b/bins/4B0906018DH.bin new file mode 100644 index 0000000..404eeca Binary files /dev/null and b/bins/4B0906018DH.bin differ diff --git a/bins/4B0906018Q.bin b/bins/4B0906018Q.bin new file mode 100644 index 0000000..22c5f23 Binary files /dev/null and b/bins/4B0906018Q.bin differ diff --git a/bins/4B0906018R.bin b/bins/4B0906018R.bin new file mode 100644 index 0000000..77e469e Binary files /dev/null and b/bins/4B0906018R.bin differ diff --git a/bins/4B0907551AA.bin b/bins/4B0907551AA.bin new file mode 100644 index 0000000..b8d7228 Binary files /dev/null and b/bins/4B0907551AA.bin differ diff --git a/bins/4B0907551AH.bin b/bins/4B0907551AH.bin new file mode 100644 index 0000000..436505d Binary files /dev/null and b/bins/4B0907551AH.bin differ diff --git a/bins/4B0907551AL.bin b/bins/4B0907551AL.bin new file mode 100644 index 0000000..8448a95 Binary files /dev/null and b/bins/4B0907551AL.bin differ diff --git a/bins/4B0907551D.bin b/bins/4B0907551D.bin new file mode 100644 index 0000000..39307ed Binary files /dev/null and b/bins/4B0907551D.bin differ diff --git a/bins/4B0907551E.bin b/bins/4B0907551E.bin new file mode 100644 index 0000000..915b099 Binary files /dev/null and b/bins/4B0907551E.bin differ diff --git a/bins/4B0907551F.bin b/bins/4B0907551F.bin new file mode 100644 index 0000000..ba73fc6 Binary files /dev/null and b/bins/4B0907551F.bin differ diff --git a/bins/4B0907551G.bin b/bins/4B0907551G.bin new file mode 100644 index 0000000..4235083 Binary files /dev/null and b/bins/4B0907551G.bin differ diff --git a/bins/4B0907551K-0003.bin b/bins/4B0907551K-0003.bin new file mode 100644 index 0000000..4202393 Binary files /dev/null and b/bins/4B0907551K-0003.bin differ diff --git a/bins/4B0907551K-0005.bin b/bins/4B0907551K-0005.bin new file mode 100644 index 0000000..12cd21b Binary files /dev/null and b/bins/4B0907551K-0005.bin differ diff --git a/bins/4B0907551L.bin b/bins/4B0907551L.bin new file mode 100644 index 0000000..a4fa935 Binary files /dev/null and b/bins/4B0907551L.bin differ diff --git a/bins/4B0907551M.bin b/bins/4B0907551M.bin new file mode 100644 index 0000000..602f749 Binary files /dev/null and b/bins/4B0907551M.bin differ diff --git a/bins/4B0907551R.bin b/bins/4B0907551R.bin new file mode 100644 index 0000000..8072adc Binary files /dev/null and b/bins/4B0907551R.bin differ diff --git a/bins/4B0907551S.bin b/bins/4B0907551S.bin new file mode 100644 index 0000000..82fcf2c Binary files /dev/null and b/bins/4B0907551S.bin differ diff --git a/bins/4B0907551T.bin b/bins/4B0907551T.bin new file mode 100644 index 0000000..5116404 Binary files /dev/null and b/bins/4B0907551T.bin differ diff --git a/bins/4D0907558S.bin b/bins/4D0907558S.bin new file mode 100644 index 0000000..45b5acc Binary files /dev/null and b/bins/4D0907558S.bin differ diff --git a/bins/4D0907559D.bin b/bins/4D0907559D.bin new file mode 100644 index 0000000..a06e4e7 Binary files /dev/null and b/bins/4D0907559D.bin differ diff --git a/bins/4D1907558-0002.bin b/bins/4D1907558-0002.bin new file mode 100644 index 0000000..23c85b0 Binary files /dev/null and b/bins/4D1907558-0002.bin differ diff --git a/bins/4D1907558-0004.bin b/bins/4D1907558-0004.bin new file mode 100644 index 0000000..9cc3cb9 Binary files /dev/null and b/bins/4D1907558-0004.bin differ diff --git a/bins/4D1907558.bin b/bins/4D1907558.bin new file mode 100644 index 0000000..9cc3cb9 Binary files /dev/null and b/bins/4D1907558.bin differ diff --git a/bins/4D1907558B.bin b/bins/4D1907558B.bin new file mode 100644 index 0000000..8d00145 Binary files /dev/null and b/bins/4D1907558B.bin differ diff --git a/bins/4D1907558C.bin b/bins/4D1907558C.bin new file mode 100644 index 0000000..e975f4f Binary files /dev/null and b/bins/4D1907558C.bin differ diff --git a/bins/4D1907558D.bin b/bins/4D1907558D.bin new file mode 100644 index 0000000..a7f28b4 Binary files /dev/null and b/bins/4D1907558D.bin differ diff --git a/bins/4D1907558F.bin b/bins/4D1907558F.bin new file mode 100644 index 0000000..448dc19 Binary files /dev/null and b/bins/4D1907558F.bin differ diff --git a/bins/4E0910559E.bin b/bins/4E0910559E.bin new file mode 100644 index 0000000..7fa8f5f Binary files /dev/null and b/bins/4E0910559E.bin differ diff --git a/bins/4Z7907551.bin b/bins/4Z7907551.bin new file mode 100644 index 0000000..ea3506c Binary files /dev/null and b/bins/4Z7907551.bin differ diff --git a/bins/4Z7907551AA-disable-P1681.bin b/bins/4Z7907551AA-disable-P1681.bin new file mode 100644 index 0000000..8b853d5 Binary files /dev/null and b/bins/4Z7907551AA-disable-P1681.bin differ diff --git a/bins/4Z7907551AA.bin b/bins/4Z7907551AA.bin new file mode 100644 index 0000000..9bf0964 Binary files /dev/null and b/bins/4Z7907551AA.bin differ diff --git a/bins/4Z7907551B.bin b/bins/4Z7907551B.bin new file mode 100644 index 0000000..4b23180 Binary files /dev/null and b/bins/4Z7907551B.bin differ diff --git a/bins/4Z7907551C.bin b/bins/4Z7907551C.bin new file mode 100644 index 0000000..c014a24 Binary files /dev/null and b/bins/4Z7907551C.bin differ diff --git a/bins/4Z7907551D.bin b/bins/4Z7907551D.bin new file mode 100644 index 0000000..49a2c98 Binary files /dev/null and b/bins/4Z7907551D.bin differ diff --git a/bins/4Z7907551E.bin b/bins/4Z7907551E.bin new file mode 100644 index 0000000..9713e6a Binary files /dev/null and b/bins/4Z7907551E.bin differ diff --git a/bins/4Z7907551H.bin b/bins/4Z7907551H.bin new file mode 100644 index 0000000..ad28e6b Binary files /dev/null and b/bins/4Z7907551H.bin differ diff --git a/bins/4Z7907551K-0001.bin b/bins/4Z7907551K-0001.bin new file mode 100644 index 0000000..fd97d1e Binary files /dev/null and b/bins/4Z7907551K-0001.bin differ diff --git a/bins/4Z7907551K-0002.bin b/bins/4Z7907551K-0002.bin new file mode 100644 index 0000000..f61b238 Binary files /dev/null and b/bins/4Z7907551K-0002.bin differ diff --git a/bins/4Z7907551L.bin b/bins/4Z7907551L.bin new file mode 100644 index 0000000..b969155 Binary files /dev/null and b/bins/4Z7907551L.bin differ diff --git a/bins/4Z7907551M.bin b/bins/4Z7907551M.bin new file mode 100644 index 0000000..6384d71 Binary files /dev/null and b/bins/4Z7907551M.bin differ diff --git a/bins/4Z7907551N.bin b/bins/4Z7907551N.bin new file mode 100644 index 0000000..6be612e Binary files /dev/null and b/bins/4Z7907551N.bin differ diff --git a/bins/4Z7907551Q.bin b/bins/4Z7907551Q.bin new file mode 100644 index 0000000..c875627 Binary files /dev/null and b/bins/4Z7907551Q.bin differ diff --git a/bins/4Z7907551R-ols-corrected.bin b/bins/4Z7907551R-ols-corrected.bin new file mode 100644 index 0000000..6f9983f Binary files /dev/null and b/bins/4Z7907551R-ols-corrected.bin differ diff --git a/bins/4Z7907551R.bin b/bins/4Z7907551R.bin new file mode 100644 index 0000000..65a241b Binary files /dev/null and b/bins/4Z7907551R.bin differ diff --git a/bins/4Z7907551S-disable-P1681.bin b/bins/4Z7907551S-disable-P1681.bin new file mode 100644 index 0000000..39a8613 Binary files /dev/null and b/bins/4Z7907551S-disable-P1681.bin differ diff --git a/bins/4Z7907551S.bin b/bins/4Z7907551S.bin new file mode 100644 index 0000000..e25f1d0 Binary files /dev/null and b/bins/4Z7907551S.bin differ diff --git a/bins/4Z7907551T.bin b/bins/4Z7907551T.bin new file mode 100644 index 0000000..839f3ae Binary files /dev/null and b/bins/4Z7907551T.bin differ diff --git a/bins/8D0907551A-0002.bin b/bins/8D0907551A-0002.bin new file mode 100644 index 0000000..c409e18 Binary files /dev/null and b/bins/8D0907551A-0002.bin differ diff --git a/bins/8D0907551A-0003.bin b/bins/8D0907551A-0003.bin new file mode 100644 index 0000000..7ee523f Binary files /dev/null and b/bins/8D0907551A-0003.bin differ diff --git a/bins/8D0907551AA.bin b/bins/8D0907551AA.bin new file mode 100644 index 0000000..f67782d Binary files /dev/null and b/bins/8D0907551AA.bin differ diff --git a/bins/8D0907551B.bin b/bins/8D0907551B.bin new file mode 100644 index 0000000..6578364 Binary files /dev/null and b/bins/8D0907551B.bin differ diff --git a/bins/8D0907551C.bin b/bins/8D0907551C.bin new file mode 100644 index 0000000..3444509 Binary files /dev/null and b/bins/8D0907551C.bin differ diff --git a/bins/8D0907551D-0001.bin b/bins/8D0907551D-0001.bin new file mode 100644 index 0000000..f70a257 Binary files /dev/null and b/bins/8D0907551D-0001.bin differ diff --git a/bins/8D0907551D-0002.bin b/bins/8D0907551D-0002.bin new file mode 100644 index 0000000..e9f9d78 Binary files /dev/null and b/bins/8D0907551D-0002.bin differ diff --git a/bins/8D0907551E.bin b/bins/8D0907551E.bin new file mode 100644 index 0000000..6af897c Binary files /dev/null and b/bins/8D0907551E.bin differ diff --git a/bins/8D0907551F.bin b/bins/8D0907551F.bin new file mode 100644 index 0000000..cef90bb Binary files /dev/null and b/bins/8D0907551F.bin differ diff --git a/bins/8D0907551G-0001.bin b/bins/8D0907551G-0001.bin new file mode 100644 index 0000000..6c97a92 Binary files /dev/null and b/bins/8D0907551G-0001.bin differ diff --git a/bins/8D0907551G-0002.bin b/bins/8D0907551G-0002.bin new file mode 100644 index 0000000..edbc0b6 Binary files /dev/null and b/bins/8D0907551G-0002.bin differ diff --git a/bins/8D0907551H.bin b/bins/8D0907551H.bin new file mode 100644 index 0000000..363a7cb Binary files /dev/null and b/bins/8D0907551H.bin differ diff --git a/bins/8D0907551J.bin b/bins/8D0907551J.bin new file mode 100644 index 0000000..c0c13d0 Binary files /dev/null and b/bins/8D0907551J.bin differ diff --git a/bins/8D0907551K.bin b/bins/8D0907551K.bin new file mode 100644 index 0000000..1dc06fa Binary files /dev/null and b/bins/8D0907551K.bin differ diff --git a/bins/8D0907551L.bin b/bins/8D0907551L.bin new file mode 100644 index 0000000..1470883 Binary files /dev/null and b/bins/8D0907551L.bin differ diff --git a/bins/8D0907551M-0001.bin b/bins/8D0907551M-0001.bin new file mode 100644 index 0000000..15c7928 Binary files /dev/null and b/bins/8D0907551M-0001.bin differ diff --git a/bins/8D0907551M-0002.bin b/bins/8D0907551M-0002.bin new file mode 100644 index 0000000..37a9ba5 Binary files /dev/null and b/bins/8D0907551M-0002.bin differ diff --git a/bins/8D0907551M.ini b/bins/8D0907551M.ini new file mode 100644 index 0000000..b23b0e5 --- /dev/null +++ b/bins/8D0907551M.ini @@ -0,0 +1,7 @@ +[info] +epk=0x10007 +part_number=0x110ed +engine_id=0x110f9 +sw_version=0x1110d +hw_number=0x18400 +sw_number=0x1840a diff --git a/bins/8D0907551N.bin b/bins/8D0907551N.bin new file mode 100644 index 0000000..9af353a Binary files /dev/null and b/bins/8D0907551N.bin differ diff --git a/bins/8D0907551Q.bin b/bins/8D0907551Q.bin new file mode 100644 index 0000000..fb803a6 Binary files /dev/null and b/bins/8D0907551Q.bin differ diff --git a/bins/8D0907551T.bin b/bins/8D0907551T.bin new file mode 100644 index 0000000..b317235 Binary files /dev/null and b/bins/8D0907551T.bin differ diff --git a/bins/8E0909518AK-0003.bin b/bins/8E0909518AK-0003.bin new file mode 100644 index 0000000..7abc9e2 Binary files /dev/null and b/bins/8E0909518AK-0003.bin differ diff --git a/bins/8E0909518AK-0004.bin b/bins/8E0909518AK-0004.bin new file mode 100644 index 0000000..310945d Binary files /dev/null and b/bins/8E0909518AK-0004.bin differ diff --git a/bins/broken/4D1907558-EU3.bin b/bins/broken/4D1907558-EU3.bin new file mode 100644 index 0000000..9779092 Binary files /dev/null and b/bins/broken/4D1907558-EU3.bin differ diff --git a/bins/broken/4Z7907551R-U25AN34.bin b/bins/broken/4Z7907551R-U25AN34.bin new file mode 100644 index 0000000..1486394 Binary files /dev/null and b/bins/broken/4Z7907551R-U25AN34.bin differ diff --git a/bins/broken/8D0907551.bin b/bins/broken/8D0907551.bin new file mode 100644 index 0000000..158e7e2 Binary files /dev/null and b/bins/broken/8D0907551.bin differ diff --git a/bins/broken/ferrari360.bin b/bins/broken/ferrari360.bin new file mode 100644 index 0000000..933b412 Binary files /dev/null and b/bins/broken/ferrari360.bin differ diff --git a/bins/broken/ferrari360.ini b/bins/broken/ferrari360.ini new file mode 100644 index 0000000..26cd59e --- /dev/null +++ b/bins/broken/ferrari360.ini @@ -0,0 +1,49 @@ +# +# Ferrari 360 (For Bosch Ignition Computers) +# +# This is the base configuration for Ferrari 360 firmware dumps +# for Bosch ME7.3 firmware decoding & checksum generation +# + +[ignition] + +[info] +epk=0x1002b +epk_len=43 +part_number=0x101a2 +part_number_len=21 +#engine_id=0x10178 +#engine_id_len=21 +#sw_version=0xXXXXX +#sw_version_len=X +hw_number=0x1018c +hw_number_len=7 +sw_number=0x10197 +sw_number_len=16 + +[dumps] +dump_show=4 + +dump_1_type=String +dump_1_visible=true +dump_1_label=SW Number +dump_1_offset=0x1015f +dump_1_len=8 + +dump_2_type=String +dump_2_visible=true +dump_2_label=SW1 Number +dump_2_offset=0x10168 +dump_2_len=21 + +dump_3_type=String +dump_3_visible=true +dump_3_label=Chassis +dump_3_offset=0x10178 +dump_3_len=21 + +dump_4_type=String +dump_4_visible=true +dump_4_label=Boot Version +dump_4_offset=0x340 +dump_4_len=65 diff --git a/bins/cleanup b/bins/cleanup new file mode 100755 index 0000000..7b6b010 --- /dev/null +++ b/bins/cleanup @@ -0,0 +1,31 @@ +#!/bin/bash +for i in $*; do + box=$( ../me7sum -s $i | grep "Part Number" | sed -e 's/ //g' | cut -f 2 -d \') + ver=$( ../me7sum -s $i | grep "SW Version" | sed -e 's/ //g' | cut -f 2 -d \') + hw=$( ../me7sum -s $i | grep "HW Number" | sed -e 's/ //g' | cut -f 2 -d \' ) + ssecu=$( ../me7sum -s $i | grep "SW Number" | sed -e 's/ //g' | cut -f 2 -d \' | sed -e 's/^1037/1037-/') + + if [ -z "$box" -o -z "$ver" -o -z "$hw" -o -z "$ssecu" ]; then + echo $i box=\"$box\" ver=\"$ver\" hw=\"$hw\"ssecu=\"$ssecu\" failed >&2 + continue + fi + + outll=$box-$ver-$ssecu.bin + outl=$box-$ver.bin + out=$box.bin + + if [ "$i" = "$out" -o "$i" = "$outl" ]; then + echo -n "$box $hw-$ssecu $ver: " >&2 + echo $i \($outl\) ok >&2 + else + if [ ! -f "$out" ]; then + echo git mv $i $out + elif [ ! -f "outl" ]; then + echo git mv $i $outl + elif [ ! -f "outll" ]; then + echo git mv $i $outll + else + echo $i $outll failed >&2 + fi + fi +done diff --git a/bins/part-numbers.txt b/bins/part-numbers.txt new file mode 100644 index 0000000..a3d7382 --- /dev/null +++ b/bins/part-numbers.txt @@ -0,0 +1,80 @@ +8D0907551A 00 0261206110-1037-352345 0002 6mt NA S4 APB +8D0907551A 00 0261206110-1037-352741 0003 6mt NA S4 APB +8D0907551B 00 0261206109-1037-352738 tip NA S4 APB +8D0907551H 01 0261206774-1037-354774 6mt NA S4 APB +8D0907551J 01 0261206775-1037-354773 tip NA S4 APB +8D0907551L 01 0261207004-1037-352815 tip NA S4 APB +8D0907551M 01 0261207143-1037-354837 0001 6mt NA S4 APB +8D0907551M 01 0261207143-1037-360857 0002 6mt NA S4 APB +8D0907551T 02 0261207452-1037-362558 6mt NA S4 APB +8D0907551AA 02 0261207453-1037-370992 tip NA S4 APB + +8D0907551 98 6mt EU S4 512K +8D0907551C 98 0261206108-1037-350093 6mt EU S4 AGB 512K +8D0907551D 00 0261206382-1037-352120 0001 6mt EU S4 AGB +8D0907551D 00 0261206382-1037-350243 0002 6mt EU S4 AGB +8D0907551E 0261206376-1037-350221 EU S4 512K +8D0907551G 01 0261206776-1037-354123 0001 6mt EU S4 AZB +8D0907551G 01 0261206776-1037-360855 0002 6mt EU S4 AZB +8D0907551N 0261207144-1037-354823 6mt EU S4 AZB +8D0907551P 026120 -1037- 6mt EU S4 AZB + +8D0907551F 01 0261206635-1037-354531 6mt EU RS4 ASJ +8D0907551K 01 0261207001-1037-360387 6mt EU RS4 AZR +8D0907551Q 02 0261207141-1037-360388 6mt EU RS4 AZR + +4B0907551K 00 0261206561-1037-352413 0003 6mt NA A6 APB +4B0907551K 00 0261206561-1037-352740 0005 6mt NA A6 APB +4B0907551L 01 0261206562-1037-352815 tip NA A6 APB +4B0907551P 01 026120 -1037- 6mt NA A6 APB +4B0907551T 01 0261207005-1037-354146 tip NA A6 APB +4B0907551Q 01 026120 -1037- 6mt NA A6 APB +4B0907551AA 01 0261207140-1037-354849 6mt NA A6 APB +4B0907551AK 02 026120 -1037- 6mt NA A6 APB +4B0907551AL 02 0261207455-1037-362549 tip NA A6 APB + +4B0907551D 0261206106-1037-350070 EU A6 AJK 512K +4B0907551E 0261206017-1037-350071 EU A6 AJK 512K +4B0907551F 0261206378-1037-350239 6mt EU A6 AJK +4B0907551G 0261206380-1037-354065 EU A6 AJK +4B0907551J 026120 -1037- EU A6 AJK +4B0907551M 0261206636-1037-362560 EU A6 +4B0907551N 026120 -1037- EU A6 ARE +4B0907551R 0261207002-1037-354143 tip EU A6 AZA +4B0907551S 01 0261207003-1037-354144 EU A6 AZA +4B0907551AD 01 026120 -1037- EU A6 AZA +4B0907551AH 02 0261207462-1037-362541 tip EU A6 AZA + +4D1907558 0261207857-1037-366304 0002 EU RS6 BCY (ME7.1.1) +4D1907558 0261207857-1037-367724 0004 EU RS6 BCY (ME7.1.1) +4D1907558A 026120 -1037- EU RS6 BCY (ME7.1.1) +4D1907558B 0261208051-1037-368087 EU RS6 BCY (ME7.1.1) +4D1907558C 0261208141-1037-366443 EU RS6 BCY (ME7.1.1) +4D1907558D 0261208239-1037-368085 NA RS6 BCY (ME7.1.1) +4D1907558E 026120 -1037- CA RS6 BCY (ME7.1.1) +4D1907558F 0261208728-1037-370934 EU RS6 BRV (ME7.1.1) +4D1907558G 026120 -1037- EU RS6 BRV (ME7.1.1) +4D1907558CX 026120 -1037- EU RS6 BRV (ME7.1.1) +4D1907558DX 026120 -1037- CA RS6 BCY (ME7.1.1) +4D1907558DV 026120 -1037- CA RS6 BCY (ME7.1.1) +4D1907558EX 026120 -1037- EU RS6 BRV (ME7.1.1) + +4Z7907551 01 0261206638-1037-354809 6mt NA ar APB +4Z7907551K 01 0261207260-1037-360166 0001 tip NA ar APB +4Z7907551K 01 0261207260-1037-360860 0002 tip NA ar APB +4Z7907551L 1/2 0261207456-1037-362929 6mt NA ar APB +4Z7907551M 1/2 0261207457-1037-360997 tip NA ar APB +4Z7907551R 03 0261207769-1037-366370-A4.0.2 NA ar BEL (ME7.1.1) + 04 a6 +4Z7907551S 03 0261208288-1037-368391-A4.0.2 NA ar BEL (ME7.1.1) + 04 a6 +4Z7907551T 0261208484-1037-369096-A4.0.2 NA ar BEL (ME7.1.1) +4Z7907551AA 0261208538-1037-369097-A4.0.2 NA ar BEL (ME7.1.1) + +4Z7907551B 0261206640-1037-354547 6mt EU ar ARE +4Z7907551C 0261206641-1037-354549 EU ar ARE +4Z7907551D 02 0261207137-1037-354846 tip EU ar ARE +4Z7907551E 02 0261207134-1037-360859 EU ar ARE +4Z7907551F 02 026120 -1037- EU ARE +4Z7907551H 02 0261207138-1037-360874 tip EU ar ARE +4Z7907551N 03 0261207766-1037-366367 EU ar BES (ME7.1.1) +4Z7907551P 026120 -1037- EU BES (ME7.1.1) +4Z7907551Q 0261207768-1037-366424-A4.0.2 JP ar BES (ME7.1.1) diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..1ee1c2f --- /dev/null +++ b/build.cmd @@ -0,0 +1,28 @@ +@echo off +set CURDIR=%cd% +rem SET VSVER=10.0 +SET VSVER=2017 + +IF "%PROGRAMFILES(X86)%"=="" ( + GOTO x86 +) ELSE ( + GOTO amd64 +) + +:amd64 +SET PROGPATH=%PROGRAMFILES(X86)% +GOTO Common + +:x86 +SET PROGPATH=%PROGRAMFILES% +GOTO Common + +:Common +rem CALL "%PROGPATH%\Microsoft Visual Studio %VSVER%\VC\vcvarsall.bat" x86 +echo "%PROGRAMFILES(X86)%\Microsoft Visual Studio\%VSVER%\Community\VC\Auxiliary\Build\vcvarsall.bat" +CALL "%PROGRAMFILES(X86)%\Microsoft Visual Studio\%VSVER%\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 + +cd %CURDIR% +for /f "usebackq" %%i in ( `git describe --tags "--abbrev=4" --dirty --always` ) do SET GIT_VERSION=%%i + +nmake %1 diff --git a/crc32.c b/crc32.c index 56a8dbd..c09c7ab 100644 --- a/crc32.c +++ b/crc32.c @@ -42,7 +42,7 @@ #include "crc32.h" -static uint32_t crc32_tab[] = { +const uint32_t crc32_tab[1024/4] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, diff --git a/crc32.h b/crc32.h index e370e6a..818f75d 100644 --- a/crc32.h +++ b/crc32.h @@ -4,6 +4,7 @@ #include #include -uint32_t crc32(uint32_t crc, const void *buf, size_t size); +extern const uint32_t crc32_tab[1024/4]; +extern uint32_t crc32(uint32_t crc, const void *buf, size_t size); #endif diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..fa24022 --- /dev/null +++ b/debug.h @@ -0,0 +1,74 @@ +#define DEBUG_PRINTF_YES printf +#define DEBUG_PRINTF_NO(...) + +#define DEBUG_FLUSH_YES printf("\n") +#define DEBUG_FLUSH_NO fflush(stdout) + +#define DEBUG_EXIT_YES exit(-1) + +#ifdef DEBUG_ROM_INFO +#define DEBUG_ROM DEBUG_PRINTF_YES +#define DEBUG_EXIT_ROM DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_ROM DEBUG_PRINTF_NO +#define DEBUG_EXIT_ROM +#endif + +#ifdef DEBUG_ROMSYS_MATCHING +#define DEBUG_ROMSYS DEBUG_PRINTF_YES +#define DEBUG_EXIT_ROMSYS DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_ROMSYS DEBUG_PRINTF_NO +#define DEBUG_EXIT_ROMSYS +#endif + +#ifdef DEBUG_CRC_MATCHING +#define DEBUG_CRC DEBUG_PRINTF_YES +#define DEBUG_FLUSH_CRC DEBUG_FLUSH_YES +#define DEBUG_EXIT_CRC DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_CRC DEBUG_PRINTF_NO +#define DEBUG_FLUSH_CRC DEBUG_FLUSH_NO +#define DEBUG_EXIT_CRC +#endif + +#ifdef DEBUG_ROMSYS_PP_MATCHING +#define DEBUG_EXIT_ROMSYS_PP DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_EXIT_ROMSYS_PP +#endif + +#ifdef DEBUG_RSA_MATCHING +#define DEBUG_RSA DEBUG_PRINTF_YES +#define DEBUG_EXIT_RSA DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_RSA DEBUG_PRINTF_NO +#define DEBUG_EXIT_RSA +#endif + +#ifdef DEBUG_MAIN_MATCHING +#define DEBUG_MAIN DEBUG_PRINTF_YES +#define DEBUG_FLUSH_MAIN DEBUG_FLUSH_YES +#define DEBUG_EXIT_MAIN DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_MAIN DEBUG_PRINTF_NO +#define DEBUG_FLUSH_MAIN DEBUG_FLUSH_NO +#define DEBUG_EXIT_MAIN +#endif + +#ifdef DEBUG_MULTIPOINT_MATCHING +#define DEBUG_MULTIPOINT DEBUG_PRINTF_YES +#define DEBUG_FLUSH_MULTIPOINT DEBUG_FLUSH_YES +#define DEBUG_EXIT_MULTIPOINT DEBUG_EXIT_YES +#define DEBUG_YES +#else +#define DEBUG_MULTIPOINT DEBUG_PRINTF_NO +#define DEBUG_FLUSH_MULTIPOINT DEBUG_FLUSH_NO +#define DEBUG_EXIT_MULTIPOINT +#endif diff --git a/ferrari360.ini b/ferrari360.ini deleted file mode 100644 index 9317ce6..0000000 --- a/ferrari360.ini +++ /dev/null @@ -1,68 +0,0 @@ -# -# Ferrari 360 (For Bosch Ignition Computers) -# -# This is the base configuration for Ferrari 360 firmware dumps -# for Bosch ME7.3 firmware decoding & checksum generation -# - -[ignition] -rom_firmware_start=0x800000 - -# main rom checksums -rom_checksum_offset=0x01bc88 -rom_checksum_final=0x07ffe0 - -# multipoint checksums -rom_checksum_block_start=0x1fc20 - -# rom data segment information dumps -[dumps] -dump_show=8 - -dump_1_type=String -dump_1_visible=true -dump_1_label=EPK : -dump_1_offset=0x1002b -dump_1_len=43 - -dump_2_type=String -dump_2_visible=true -dump_2_label=SW Number : -dump_2_offset=0x1015f -dump_2_len=8 - -dump_3_type=String -dump_3_visible=true -dump_3_label=SW1 Number : -dump_3_offset=0x10168 -dump_3_len=15 - -dump_4_type=String -dump_4_visible=true -dump_4_label=Chassis : -dump_4_offset=0x10178 -dump_4_len=15 - -dump_5_type=String -dump_5_visible=true -dump_5_label=Bosch ECU HW Number: -dump_5_offset=0x1018c -dump_5_len=7 - -dump_6_type=String -dump_6_visible=true -dump_6_label=Bosch ECU SW Number: -dump_6_offset=0x10197 -dump_6_len=10 - -dump_7_type=String -dump_7_visible=true -dump_7_label=Part Number : -dump_7_offset=0x101a2 -dump_7_len=15 - -dump_8_type=String -dump_8_visible=true -dump_8_label=Boot Version : -dump_8_offset=0x340 -dump_8_len=41 diff --git a/helper.pl b/helper.pl new file mode 100755 index 0000000..3ede196 --- /dev/null +++ b/helper.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +use strict; +use Data::Dumper; + +my @ary; +my $len=0; + +while (<>) { + chomp; + s/\/\///; + s/#//; + s/\s+//; + my @a=(split(' ',$_)); + next unless scalar(@a); + $len = scalar(@a) if (scalar(@a)>$len); + push @ary, \@a; +} + +my @needle = (0xff) x $len; +my @mask = (0) x $len; + +#print Dumper(\@ary); + +for (my $i=0; $i<$len; $i++) { + my @col = map $_->[$i], @ary; + for my $v (@col) { + $needle[$i] &= hex($v); + $mask[$i] |= hex($v); + } +} + +for (my $i=0; $i<$len; $i++) { + printf("0x%02x,", $needle[$i]&0xff); +} +print "\n"; + +for (my $i=0; $i<$len; $i++) { + printf("0x%02x,", ($needle[$i] | ~$mask[$i])&0xff); +} +print "\n"; + + diff --git a/inifile/inifile.c b/inifile/inifile.c index cb0c96d..b0d71f3 100644 --- a/inifile/inifile.c +++ b/inifile/inifile.c @@ -1,7 +1,14 @@ #include #include #include -#include // added back in, unable to compile under win32 mingw without it. (for write() function) + +#ifdef _MSC_VER +#include +typedef SSIZE_T ssize_t; +#else +#include +#endif + #include "inifile.h" static char *trimstr(char *s, char *end) @@ -18,7 +25,7 @@ static char *trimstr(char *s, char *end) else break; } - if (end == s) return NULL; + if (end <= s) return NULL; t = str = (char *) malloc(end - s + 1); while (s < end) @@ -52,7 +59,7 @@ static char *trimstr(char *s, char *end) return str; } -struct section *find_section(struct section *sect, char *name) +const struct section *find_section(const struct section *sect, const char *name) { while (sect) { @@ -81,7 +88,7 @@ int get_section_size(struct section *sect) return n; } -char *find_property(struct section *sect, char *name) +const char *find_property(const struct section *sect, const char *name) { struct property *prop; @@ -97,21 +104,23 @@ char *find_property(struct section *sect, char *name) return NULL; } -char *get_property(struct section *sections, char *sectname, char *propname, char *defval) +const char *get_property(struct section *sections, const char *sectname, const char *propname, const char *defval) { - struct section *sect; - char *val; + const struct section *sect; + const char *val; sect = find_section(sections, sectname); + // must return a pointer that can be freed! if (!sect) return defval; val = find_property(sect, propname); + // must return a pointer that can be freed! return val ? val : defval; } -int get_numeric_property(struct section *sections, char *sectname, char *propname, int defval) +int get_numeric_property(struct section *sections, const char *sectname, const char *propname, int defval) { - char *val; + const char *val; val = get_property(sections, sectname, propname, NULL); return val ? atoi(val) : defval; @@ -251,9 +260,9 @@ struct section *parse_properties(char *props) return secthead; } -int dump_section_properties(struct section *sections, char *sectname) +int dump_section_properties(struct section *sections, const char *sectname) { - struct section *sect; + const struct section *sect; struct property *prop; sect = find_section(sections, sectname); @@ -268,30 +277,40 @@ int dump_section_properties(struct section *sections, char *sectname) return 0; } +static ssize_t safe_write(int fd, const void *buf, size_t count) +{ + ssize_t ret = write(fd, buf, count); + if (ret<0) { + perror("write"); + exit(1); + } + return ret; +} + void list_properties(int f, struct section *sect) { struct property *prop; while (sect) { - write(f, "[", 1); - write(f, sect->name, strlen(sect->name)); - write(f, "]\r\n", 3); + safe_write(f, "[", 1); + safe_write(f, sect->name, strlen(sect->name)); + safe_write(f, "]\r\n", 3); prop = sect->properties; while (prop) { - write(f, prop->name, strlen(prop->name)); + safe_write(f, prop->name, strlen(prop->name)); if (prop->value) { - write(f, "=", 1); - write(f, prop->value, strlen(prop->value)); + safe_write(f, "=", 1); + safe_write(f, prop->value, strlen(prop->value)); } - write(f, "\r\n", 2); + safe_write(f, "\r\n", 2); prop = prop->next; } - if (sect->next) write(f, "\r\n", 2); + if (sect->next) safe_write(f, "\r\n", 2); sect = sect->next; } } @@ -300,7 +319,7 @@ void list_properties(int f, struct section *sect) #include #include -struct section *read_properties(char *filename) +struct section *read_properties(const char *filename) { FILE *f; int size, siz; diff --git a/inifile/inifile.h b/inifile/inifile.h index 8a97e26..1347071 100644 --- a/inifile/inifile.h +++ b/inifile/inifile.h @@ -54,16 +54,16 @@ struct property extern "C" { #endif -struct section *find_section(struct section *sect, char *name); +const struct section *find_section(const struct section *sect, const char *name); int get_section_size(struct section *sect); -char *find_property(struct section *sect, char *name); -char *get_property(struct section *sections, char *sectname, char *propname, char *defval); -int get_numeric_property(struct section *sections, char *sectname, char *propname, int defval); +const char *find_property(const struct section *sect, const char *name); +const char *get_property(struct section *sections, const char *sectname, const char *propname, const char *defval); +int get_numeric_property(struct section *sections, const char *sectname, const char *propname, int defval); void free_properties(struct section *sect); struct section *parse_properties(char *props); void list_properties(int f, struct section *sect); -struct section *read_properties(char *filename); -int dump_section_properties(struct section *sections, char *sectname); +struct section *read_properties(const char *filename); +int dump_section_properties(struct section *sections, const char *sectname); #ifdef __cplusplus } diff --git a/inifile/makefile b/inifile/makefile index 10663bc..1807941 100644 --- a/inifile/makefile +++ b/inifile/makefile @@ -4,5 +4,3 @@ include ../vars.mk LIB =libini.a include ../makefile.common - -inifile.o: inifile.c inifile.h diff --git a/inifile_prop.c b/inifile_prop.c index 76c78b3..d4b271f 100644 --- a/inifile_prop.c +++ b/inifile_prop.c @@ -1,32 +1,32 @@ #include #include #include + +#include "os/os.h" #include "inifile_prop.h" -uint32_t get_property_value(struct section *sections, char *sectname, char *propname, char *def) +uint32_t get_property_value(struct section *sections, const char *sectname, const char *propname, const char *def) { uint32_t val=0; uint32_t defval=0; - char *pStr=0; + const char *pStr=0; // get default value string (if exists) if(def != NULL) { - defval=strtoul(def, NULL, 16); + defval=strtoul(def, NULL, 0); } // lookup property pStr = get_property(sections, sectname, propname, NULL); // success? if(pStr != NULL) { // scan property value - val=strtoul(pStr, NULL, 16); - free(pStr); + val = strtoul(pStr, NULL, 0); } else { val = defval; } return val; } - int process_properties_list(struct section *osconfig, PropertyListItem *ci) { int i=0,type,errCount=0; @@ -52,7 +52,40 @@ int process_properties_list(struct section *osconfig, PropertyListItem *ci) } i++; } - printf("Processed %d elements with %d issues\n",i,errCount); + // printf("Processed %d elements with %d issues\n",i,errCount); + return errCount; +} + +int process_info_list(struct section *osconfig, InfoListItem *ci) +{ + int i=0,type,errCount=0; + InfoItem *pItem; + + while(1) { + type = ci[i].attr_type; + if(type == END_LIST) break; // exit list... + if(type == GET_VALUE) { // process list entry for GET_VALUE type + pItem = ci[i].item; + if(pItem != 0) { + char str_len[81]; + pItem->off = get_property_value(osconfig, ci[i].attr_path, ci[i].attr_name, ci[i].attr_default); + // printf("get_property_value( %s, %s)\n",ci[i].attr_path,ci[i].attr_name); + snprintf(str_len, sizeof(str_len), "%s_len", ci[i].attr_name); + pItem->len = get_property_value(osconfig, ci[i].attr_path, str_len, ci[i].attr_default_len); + // printf("get_property_value( %s, %s)\n",ci[i].attr_path, str_len); + if(pItem->off == 0) { + errCount++; + // printf("Warning: Failed to get value for %s %s\n",ci[i].attr_path, ci[i].attr_name); + } + } else { + printf("Error: Invalid storage for property, check property list definition, item %d\n",i); + } + } else { + printf("Unsupported property accessor type, check propertylist, item %d\n", i); + } + i++; + } + // printf("Processed %d elements with %d issues\n",i,errCount); return errCount; } diff --git a/inifile_prop.h b/inifile_prop.h index bf14af9..1592543 100644 --- a/inifile_prop.h +++ b/inifile_prop.h @@ -9,25 +9,42 @@ extern "C" { #endif -#define END_LIST -1 -#define GET_VALUE 1 -#define GET_STRING 2 -#define ATTR_MAX_PATH 64 -#define ATTR_MAX_NAME 128 +#define END_LIST -1 +#define GET_VALUE 1 +#define GET_STRING 2 + typedef struct PropertyListItem { int attr_type; uint32_t *attr_adr; - char attr_path[ATTR_MAX_PATH]; - char attr_name[ATTR_MAX_NAME]; - char attr_default[ATTR_MAX_NAME]; + const char *attr_path; + const char *attr_name; + const char *attr_default; } PropertyListItem; -uint32_t get_property_value(struct section *sections, char *sectname, char *propname, char *def); +typedef struct InfoItem { + uint32_t off; + uint32_t len; +} InfoItem; + +typedef struct InfoListItem { + const char *label; + int attr_type; + InfoItem *item; + const char *attr_path; + const char *attr_name; + const char *attr_default; + const char *attr_default_len; +} InfoListItem; + +uint32_t get_property_value(struct section *sections, const char *sectname, const char *propname, const char *def); int process_properties_list(struct section *osconfig, PropertyListItem *ci); +int process_info_list(struct section *osconfig, InfoListItem *ci); #ifdef __cplusplus } #endif #endif + +// vim:ts=4:sw=4 diff --git a/list.h b/list.h new file mode 100644 index 0000000..5474716 --- /dev/null +++ b/list.h @@ -0,0 +1,266 @@ +#ifndef __LIST_H +#define __LIST_H + +/* This file is from Linux Kernel (include/linux/list.h) + * and modified by simply removing hardware prefetching of list items. + * Here by copyright, credits attributed to wherever they belong. + * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#ifdef _MSC_VER + /* MS does not have typeof, so list MUST be first in struct */ + #define _typeof(x) void + #define off_of(type, member) (0) + #define inline __inline +#else + #include + #define _typeof typeof + #define off_of(type, member) offsetof(type, member) +#endif + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-off_of(type, member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, _typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, _typeof(*pos), member)) + +/** + * list_for_each_entry_prev - iterate over list of given type backwards + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_prev(pos, head, member) \ + for (pos = list_entry((head)->prev, _typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, _typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, _typeof(*pos), member), \ + n = list_entry(pos->member.next, _typeof(*pos), member);\ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, _typeof(*n), member)) + + +#endif diff --git a/load_file.c b/load_file.c deleted file mode 100644 index cdabda2..0000000 --- a/load_file.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Simple load file into memory - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -*/ -#include "load_file.h" - -/* load a file into memory and return buffer */ -unsigned char *load_file(char *filename, size_t *filelen) -{ - FILE *fp; - unsigned char *data; - size_t size,bytesRead; - - /* open file */ - printf("þ Opening '%s' file\n",filename); - if ((fp = (FILE *)fopen(filename, "rb")) == NULL){ printf("\nCan't open file \"%s\".", filename); return(0); } - - /* get file length */ - printf("þ Getting length of '%s' file\n",filename); - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); - if(size <= 0) { printf("Error: Problem with seeking filesize\n"); fclose(fp); return(0); } - - *filelen = size; /* return size of file to caller */ - - /* alloc buffer for file */ - printf("þ Allocating buffer of %d bytes\n",size); - data = (unsigned char *)malloc(size); - if(data == 0) { printf("\nfailed to allocate memory to load module\n"); fclose(fp); return 0; } - - /* load file into buffer */ - printf("þ Reading file to buffer\n"); - bytesRead = fread(data, 1, size, fp); - - /* validate it all loaded correctly */ - printf("þ Validating size correct %d=%d\n",bytesRead,size); - if(bytesRead != size) { printf("\nfailed to load module into buffer\n"); free(data); fclose(fp); return 0; } - - /* close the file */ - printf("þ Closing file\n\n"); - fclose(fp); - return(data); -} diff --git a/load_file.h b/load_file.h deleted file mode 100644 index a85f86b..0000000 --- a/load_file.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Simple read file into memory - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -*/ -#ifndef _LOAD_FILE_H_ -#define _LOAD_FILE_H_ - -#include -#include -#include - -unsigned char *load_file(char *filename, size_t *filelen); - -#endif diff --git a/makefile b/makefile index bb7def4..2933558 100644 --- a/makefile +++ b/makefile @@ -1,13 +1,14 @@ -include vars.mk - -EXE =me7sum$(EXE_EXT) -LIBS =ini -SUBDIRS =inifile -LDFLAGS=-Linifile - -include makefile.common - -me7sum.o: me7sum.c crc32.h utils.h inifile_prop.h inifile/inifile.h -inifile_prop.o: inifile_prop.h inifile/inifile.h -crc32.o: crc32.h -utils.o: utils.h +# FOR MSVSS nmake only + +TARGET = me7sum.exe +SOURCES = crc32.c inifile_prop.c me7sum.c utils.c str.c range.c inifile/inifile.c os/pgetopt.c rsa.c md5.c +LIBRARIES = Ws2_32.lib mpir/mpir-2017.lib + +CFLAGS = -D__GIT_VERSION=\"$(GIT_VERSION)\" + +all: $(TARGET) +$(TARGET):$(SOURCES) + cl /EHsc /Fe$@ $(CFLAGS) /Tc $(SOURCES) $(LIBRARIES) + +clean: + del $(TARGET) *.obj diff --git a/makefile.common b/makefile.common index 3b677b8..caee29c 100644 --- a/makefile.common +++ b/makefile.common @@ -1,5 +1,7 @@ +# included by GNUMakefile and inifile/makefile OBJ =$(SRC:.c=.o) # replaces the .c from SRC with .o +DEPS =$(SRC:.c=.d) # replaces the .c from SRC with .d %.o: %.c # combined w/ next line will compile recently changed .c files $(ECHO) Compiling $(notdir $<) ... @@ -19,13 +21,20 @@ $(LIB): $(OBJ) $(EXE): $(OBJ) # $(EXE) is dependent on all of the files in $(OBJ) to exist $(ECHO) Linking $@ ... - $(DEBUG)$(CC) $(OBJ) $(LDFLAGS) $(addprefix -l,$(LIBS)) -o $@ + $(DEBUG)$(LD) $(OBJ) $(LDFLAGS) $(addprefix -l,$(LIBS)) -o $@ $(ECHO) Done .PHONY : clean # .PHONY ignores files named clean clean: TARGET := clean clean: $(SUBDIRS) - $(ECHO) Deleting $(OBJ) $(LIB) $(EXE) ... - $(DEBUG)-$(RM) $(OBJ) $(LIB) $(EXE) + $(ECHO) Deleting $(OBJ) $(DEPS) $(LIB) $(EXE) ... + $(DEBUG)-$(RM) $(OBJ) $(DEPS) $(LIB) $(EXE) +.PHONY: force +.compiler_flags: force + @echo '$(CDEFS)' | cmp -s - $@ || echo '$(CDEFS)' > $@ + +$(OBJ): .compiler_flags + +-include $(DEPS) diff --git a/md5.c b/md5.c new file mode 100644 index 0000000..52d96ac --- /dev/null +++ b/md5.c @@ -0,0 +1,296 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#ifndef HAVE_OPENSSL + +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + available = 64 - used; + + if (size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if (available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif diff --git a/md5.h b/md5.h new file mode 100644 index 0000000..2da44bf --- /dev/null +++ b/md5.h @@ -0,0 +1,45 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +#ifdef HAVE_OPENSSL +#include +#elif !defined(_MD5_H) +#define _MD5_H + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +extern void MD5_Init(MD5_CTX *ctx); +extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +#endif diff --git a/me7sum.c b/me7sum.c index 25d6c66..071f7dc 100644 --- a/me7sum.c +++ b/me7sum.c @@ -1,4 +1,4 @@ -/* me7sum [ firmware management tool for Bosch ME7.x firmware] +/* me7sum [firmware management tool for Bosch ME7.x firmware] By 360trev and nyet Inspired by work from Andy Whittaker's (tools and information) @@ -30,18 +30,42 @@ #include #include #include +#include #include +#include /* isprint() */ + +#include "os/os.h" #include "inifile_prop.h" #include "crc32.h" +#include "str.h" #include "utils.h" +#include "range.h" +#include "md5.h" +#include "rsa.h" + +//#define DEBUG_ROM_INFO +//#define DEBUG_ROMSYS_MATCHING +//#define DEBUG_CRC_MATCHING +//#define DEBUG_ROMSYS_PP_MATCHING +//#define DEBUG_RSA_MATCHING +//#define DEBUG_MAIN_MATCHING +//#define DEBUG_MULTIPOINT_MATCHING + +#include "debug.h" + +#define CHECK_BOOTROM_MP +#define RSA_MODULUS_SIZE 1024 +#define RSA_BLOCK_SIZE (RSA_MODULUS_SIZE/8) + +/* Images with 2+64 main mp descriptors do not have an end marker */ +#ifdef CHECK_BOOTROM_MP +#define MAX_MP_BLOCK_LEN 66 +#else +#define MAX_MP_BLOCK_LEN 64 +#endif // structures -struct Range { - uint32_t start; - uint32_t end; -}; - struct ChecksumPair { uint32_t v; // value uint32_t iv; // inverse value @@ -52,247 +76,2188 @@ struct MultipointDescriptor { struct ChecksumPair csum; }; -// globals +#if 0 +static int sbhexdump(struct strbuf *buf, const void *p, int len) +{ + int i=len; + int ret=0; + const uint8_t *ptr=p; + while(i--) + ret+=sbprintf(buf, "%02x%s", *ptr++, ((i&0xf)==0 && len>32)?"\n":i?" ":""); + return ret; +} -static int ErrorsFound = 0; -static int ErrorsCorrected = 0; +static int sbprintdesc(struct strbuf *buf, const struct MultipointDescriptor *d) +{ + int ret=sbprintf(buf, " "); + ret+=sbhexdump(buf, d, sizeof(*d)); + ret+=sbprintf(buf, "\n"); + ret+=sbprintf(buf, " %x-%x %x %x\n", d->r.start, d->r.end, d->csum.v, d->csum.iv); + return ret; +} +#endif +#ifndef __GIT_VERSION +#define __GIT_VERSION "unknown" +#endif + +#define MAX_CRC_BLKS 4 +#define MD5_MAX_BLKS 4 // main firmware checksum validation struct rom_config { int readonly; uint32_t base_address; /* rom base address */ - uint32_t multipoint_block_start; /* start of multipoint block descriptors */ - uint32_t multipoint_block_len; /* size of descriptors */ + + struct { + uint32_t n; /* offset of modulus */ + uint32_t e; /* offset of exponent */ + uint32_t s; /* offset of signature */ + uint32_t ds; /* offset of default signature (unused?) */ + int exponent; /* actual exponent */ + struct Range md5[MD5_MAX_BLKS]; + } rsa; + uint32_t romsys; + uint32_t crctab[2]; + uint32_t multipoint_block_start[2]; /* start of multipoint block descriptors (two sets, first one isn't always there) */ + uint32_t multipoint_desc_len; /* size of descriptors */ uint32_t main_checksum_offset; /* two start/end pairs, one at offset, other at offset+8 */ uint32_t main_checksum_final; /* two 4 byte checksum (one inv) for two blocks conctatenated above) */ struct { struct Range r; uint32_t offset; - } crc[3]; /* 3 CRC blocks to check */ -} Config; + } crc[MAX_CRC_BLKS+1]; /* 0/4 is pre-region (for kbox and other) Up to 5 CRC blocks (total) to check */ + uint32_t csm_offset; /* ME7.1.1 */ +}; + +struct info_config { + InfoItem EPK; + InfoItem sw_number; + InfoItem hw_number; + InfoItem part_number; + InfoItem sw_version; + InfoItem engine_id; +}; + +// globals +static FILE *ReportFile = NULL; +static struct rom_config Config; +static struct info_config InfoConfig; +#ifdef DEBUG_YES +static int Verbose = 2; +#else +static int Verbose = 0; +#endif -// boot sector validation (optional, generally already in multipoint blocks above) */ -struct rom_boot_config { - struct Range addr; - uint32_t checksum; -} BootConfig; +static int ChecksumsFound = 0; +static int ErrorsUncorrectable = 0; +static int ErrorsFound = 0; +static int ErrorsCorrected = 0; // // List of configurable properties to read from config file into our programme... // [this stops us having to hardcode values into the code itself] // -PropertyListItem romProps[] = { +static PropertyListItem romProps[] = { // get rom region information - { GET_VALUE, &Config.base_address, "ignition", "rom_firmware_start", "0"}, - { GET_VALUE, &Config.multipoint_block_start, "ignition", "rom_checksum_block_start", "0"}, - { GET_VALUE, &Config.multipoint_block_len, "ignition", "rom_checksum_block_len", "0x10"}, + { GET_VALUE, &Config.base_address, "ignition", "rom_firmware_start", "0x800000"}, + { GET_VALUE, &Config.multipoint_block_start[0], "ignition", "rom_checksum_block_start0", "0"}, + { GET_VALUE, &Config.multipoint_block_start[1], "ignition", "rom_checksum_block_start", "0"}, + { GET_VALUE, &Config.multipoint_desc_len, "ignition", "rom_checksum_desc_len", "0x10"}, { GET_VALUE, &Config.main_checksum_offset, "ignition", "rom_checksum_offset", "0"}, { GET_VALUE, &Config.main_checksum_final, "ignition", "rom_checksum_final", "0"}, - { GET_VALUE, &Config.crc[0].r.start, "ignition", "rom_crc1_start", "0"}, - { GET_VALUE, &Config.crc[0].r.end, "ignition", "rom_crc1_end", "0"}, - { GET_VALUE, &Config.crc[0].offset, "ignition", "rom_crc1", "0"}, - { GET_VALUE, &Config.crc[1].r.start, "ignition", "rom_crc2_start", "0"}, - { GET_VALUE, &Config.crc[1].r.end, "ignition", "rom_crc2_end", "0"}, - { GET_VALUE, &Config.crc[1].offset, "ignition", "rom_crc2", "0"}, - { GET_VALUE, &Config.crc[2].r.start, "ignition", "rom_crc3_start", "0"}, - { GET_VALUE, &Config.crc[2].r.end, "ignition", "rom_crc3_end", "0"}, - { GET_VALUE, &Config.crc[2].offset, "ignition", "rom_crc3", "0"}, + { GET_VALUE, &Config.crc[0].r.start, "ignition", "rom_crc0_start", "0"}, + { GET_VALUE, &Config.crc[0].r.end, "ignition", "rom_crc0_end", "0"}, + { GET_VALUE, &Config.crc[1].r.start, "ignition", "rom_crc1_start", "0"}, + { GET_VALUE, &Config.crc[1].r.end, "ignition", "rom_crc1_end", "0"}, + { GET_VALUE, &Config.crc[1].offset, "ignition", "rom_crc1", "0"}, + { GET_VALUE, &Config.crc[2].r.start, "ignition", "rom_crc2_start", "0"}, + { GET_VALUE, &Config.crc[2].r.end, "ignition", "rom_crc2_end", "0"}, + { GET_VALUE, &Config.crc[2].offset, "ignition", "rom_crc2", "0"}, + { GET_VALUE, &Config.crc[3].r.start, "ignition", "rom_crc3_start", "0"}, + { GET_VALUE, &Config.crc[3].r.end, "ignition", "rom_crc3_end", "0"}, + { GET_VALUE, &Config.crc[3].offset, "ignition", "rom_crc3", "0"}, + { GET_VALUE, &Config.crc[4].r.start, "ignition", "rom_crc4_start", "0"}, + { GET_VALUE, &Config.crc[4].r.end, "ignition", "rom_crc4_end", "0"}, + { GET_VALUE, &Config.crc[4].offset, "ignition", "rom_crc4", "0"}, { END_LIST, 0, "",""}, }; -static int GetRomInfo(struct ImageHandle *ih, struct section *osconfig, uint32_t num_of); -static int DoMainCRCs(struct ImageHandle *ih); -static int DoMainChecksum(struct ImageHandle *ih); -static int DoChecksumBlks(struct ImageHandle *ih, uint32_t nStartBlk); +static InfoListItem romInfo[] = { + // get rom region information + { "EPK", GET_VALUE, &InfoConfig.EPK, "info", "epk", "0", "41"}, + { "Part Number", GET_VALUE, &InfoConfig.part_number, "info", "part_number", "0", "12"}, + { "Engine ID", GET_VALUE, &InfoConfig.engine_id, "info", "engine_id", "0", "17"}, + { "SW Version", GET_VALUE, &InfoConfig.sw_version, "info", "sw_version", "0", "4"}, + { "HW Number", GET_VALUE, &InfoConfig.hw_number, "info", "hw_number", "0", "10"}, + { "SW Number", GET_VALUE, &InfoConfig.sw_number, "info", "sw_number", "0", "10"}, + { NULL,END_LIST,NULL,NULL,NULL} +}; + +static int FindRomInfo(const struct ImageHandle *ih); +static int DoRomInfo(const struct ImageHandle *ih, struct section *osconfig); + +static int FindROMSYS(struct ImageHandle *ih); +static int DoROMSYS(struct ImageHandle *ih); // Startup in RSA, MP; ParamPage in RSA, MP, Main CSM, Main CRC + +static int FindMainCRCPreBlk(const struct ImageHandle *ih); +static int FindMainCRCBlks(const struct ImageHandle *ih); +static int FindMainCRCOffsets(const struct ImageHandle *ih); +static int DoMainCRCs(struct ImageHandle *ih); // In ROMSYS Program Pages (sometimes), Main CSM, MP + +static int FindMainCSMOffsets(const struct ImageHandle *ih); +static int DoMainCSMs(struct ImageHandle *ih); // In Main Program CSM, MP + +static int DoROMSYS_ProgramPages(struct ImageHandle *ih); // In RSA (sometimes, in tuned files), MP + +static int FindRSAOffsets(struct ImageHandle *ih); +static int FindMD5Ranges(struct ImageHandle *ih); +static int DoRSA(struct ImageHandle *ih); // In Main Program CSM, MP + +static int FindCRCTab(const struct ImageHandle *ih); +static int DoCRCTab(struct ImageHandle *ih); + +static int FindMainProgramOffset(const struct ImageHandle *ih); +static int FindMainProgramFinal(const struct ImageHandle *ih); +static int DoMainProgramCSM(struct ImageHandle *ih); // In MP + +static int FindChecksumBlks(const struct ImageHandle *ih, int which); +static int DoChecksumBlk(struct ImageHandle *ih, uint32_t nStartBlk, struct strbuf *buf, int bootrom); + +static void usage(const char *prog) +{ + printf("Usage: %s [-v] [-i ] [outrom.bin]\n", prog); + printf(" %s [-v] [-i ] [-r ] [-s] \n", prog); + exit(-1); +} + +static int bytecmp(const void *buf, uint8_t byte, size_t len) +{ + int i; + const uint8_t *p=buf; + for(i=0;ibootrom_whitelist if whitelisted */ +/* returns -1 if not in whitelist AND does not match next pair of non-bootrom descriptors */ +static int check_whitelist(struct ImageHandle *ih, uint32_t addr) +{ + struct MultipointDescriptor desc[4]; + /* Check for hardcoded bootrom csums... if there, treat as ok */ + static const uint32_t whitelist[][2] = {{0x0fa0f5cf, 0x0f4716b3}, + {0x0e59d5c8, 0x1077fb35}}; + int i; + + for(i=0;i<4;i++) + memcpy_from_le32(desc+i, ih->d.u8+addr+Config.multipoint_desc_len*i, + sizeof(struct MultipointDescriptor)); + + for(i=0;i<2;i++) { + if (desc[i].r.start>=desc[i].r.end) return 0; + if (desc[i].r.start>=Config.base_address) return 0; + if (desc[i].r.end>=Config.base_address) return 0; + } + + if (desc[0].r.start!=0 || desc[0].r.end!=0x3fff) return 0; + if (desc[1].r.start!=0x4000 || desc[1].r.end!=0x7fff) return 0; + + for(i=0;i<2;i++) { + if (desc[0].csum.v==~desc[0].csum.iv && + desc[1].csum.v==~desc[1].csum.iv && + whitelist[i][0]==desc[0].csum.v && + whitelist[i][1]==desc[1].csum.v) { + ih->bootrom_whitelist=1; + return 1; + } + } + + if ((desc[0].csum.v != desc[2].csum.v) || + (desc[1].csum.v != desc[3].csum.v) || + (desc[0].csum.iv != desc[2].csum.iv) || + (desc[1].csum.iv != desc[3].csum.iv)) { + printf("ERROR! Inconsistency in non-whitelisted bootrom multipoint descriptors!\n"); + ErrorsUncorrectable++; + return -1; + } + + return 1; +} +#endif + +/* + * main() + * + */ +int main(int argc, char **argv) +{ + int Step=0; + int iTemp; + int summary=0; + char *prog=argv[0]; + char *inifile=NULL; + char *reportfile=NULL; + char *input=NULL; + char *output=NULL; + int i, c; + struct ImageHandle ih; + struct section *osconfig=NULL; + struct strbuf buf; + + memset(&buf, 0, sizeof(buf)); + + // information about the tool + printf("ME7Sum (%s) [Management tool for Bosch ME7.x firmwares]\n", + __GIT_VERSION); + printf("Inspiration from Andy Whittaker's tools and information.\n"); + printf("Written by 360trev and nyet [BSD License Open Source].\n"); + + opterr=0; + + while ((c = getopt(argc, argv, "qsvi:r:")) != -1) + { + switch (c) + { + case 'q': + Verbose--; + break; + case 's': + summary++; + break; + case 'v': + Verbose++; + break; + case 'i': + inifile=optarg; + break; + case 'r': + reportfile=optarg; + break; + case '?': + if (optopt == 'i') + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + else if (isprint(optopt)) + fprintf(stderr, "Unknown option '-%c'.\n", optopt); + // break; // fallthrough + default: + usage(prog); + return -1; + } + } + + if (Verbose<0) Verbose=0; + + argc-=optind; + argv+=optind; + + if (argc==0 || argc>2) + usage(prog); + + input = argv[0]; + + if (argc>1) + output = argv[1]; + else + Config.readonly=1; + + if (summary && output) { + fprintf(stderr, "-s cannot be used with output file\n"); + usage(prog); + return -1; + } + + if (reportfile && output) { + fprintf(stderr, "-r cannot be used with output file\n"); + usage(prog); + return -1; + } + + if (inifile) + { + printf("Attempting to open firmware config file '%s'\n",inifile); + // load properties file into memory + osconfig = read_properties(inifile); + if(osconfig == NULL) + { + fprintf(stderr, "failed to open ini file %s\n", inifile); + return -1; + } + } + + if (reportfile) { + ReportFile = fopen(reportfile, "w"); + if (!ReportFile) { + fprintf(stderr, "failed to open report file %s: %s\n", reportfile, strerror(errno)); + return -1; + } + } + + // get rom region information from config file (see defined property list) + process_properties_list(osconfig, romProps); + process_info_list(osconfig, romInfo); + + // open the firmware file + printf("\nAttempting to open firmware file '%s'\n",input); + i=iload_file(&ih, input, 0, &buf); + if (buf.pbuf) { + if (i || Verbose>1) printf("%s", buf.pbuf); + free(buf.pbuf); + } + if (i) + { + printf("Failed to open firmware file '%s'\n",input); + ErrorsFound++; + return -1; + } + + // sanity check: validate firmware file is at least 512kbytes length before proceeding. + if(ih.len != 512*1024 && ih.len != 1024*1024) + { + printf("File is an odd size (%d bytes). Are you sure this is a firmware dump?\n", + (int)ih.len); + ErrorsFound++; + goto out; + } + + if(ih.len == (1024*1024)) + { + /* Check to make sure it isn't a doubled up file or padded + with ff or 00 */ + if (memcmp(ih.d.u8, ih.d.u8+512*1024, 512*1024)==0) { + printf("File is doubled up 512k dump. Treating as 512k\n"); + ih.len=512*1024; + ih.pad = PADDING_DOUBLED; + } else if (bytecmp(ih.d.u8+512*1024, 0xff, 512*1024)==0) { + printf("File is padded from 512k to 1024k with 0xFF. Treating as 512k\n"); + ih.len=512*1024; + ih.pad = PADDING_FF; + } else if (bytecmp(ih.d.u8+512*1024, 0xff, 512*1024-32)==0) { + printf("File is padded from 512k to 1024k with 0xFF. Treating as 1024k but will try 512k CRC hardcoded blocks\n"); + ih.pad = PADDING_TRY_512K_CRC; +/* + } else if (bytecmp(ih.d.u8+512*1024, 0, 512*1024)==0) { + printf("File is padded from 512k to 1024k with zeros. Treating as 512k\n"); + ih.len=512*1024; + ih.pad = PADDING_00; +*/ + } + } + + + // + // ROM info + // + + printf("\nStep #%d: Reading ROM info ..\n", ++Step); + if(InfoConfig.part_number.off==0) + { + FindRomInfo(&ih); + } + + if(InfoConfig.part_number.off) + { + DoRomInfo(&ih, osconfig); + } + else + { + printf("Step #%d: ERROR! Skipping ROM info.. UNDEFINED\n", Step); + ErrorsUncorrectable++; + } + + if(summary && summary<=Step) goto out; + + DEBUG_EXIT_ROM; + + + // + // ROMSYS + // + printf("\nStep #%d: Reading ROMSYS ..\n", ++Step); + + if(Config.romsys==0) + { + FindROMSYS(&ih); + } + + if(Config.romsys) + { + DoROMSYS(&ih); + } + else + { + printf("Step #%d: ERROR! Skipping ROMSYS.. UNDEFINED\n", Step); + ErrorsUncorrectable++; + } + + if(summary && summary<=Step) goto out; + + DEBUG_EXIT_ROMSYS; + + // + // CRC table(s) + // + printf("\nStep #%d: Finding CRC table(s) ..\n", ++Step); + if(!Config.crctab[0]) + FindCRCTab(&ih); + if(Config.crctab[0]) { + DoCRCTab(&ih); + } else { + printf("Step #%d: ERROR! Couldn't find CRC table(s)\n", Step); + ErrorsUncorrectable++; + } + + if(summary && summary<=Step) goto out; + + + // + // RSA + // + printf("\nStep #%d: Reading RSA signatures ..\n", ++Step); + + FindRSAOffsets(&ih); + if(Config.rsa.n && Config.rsa.s && Config.rsa.e) { + FindMD5Ranges(&ih); + if (Config.rsa.md5[0].start && Config.rsa.md5[0].end) { + DoRSA(&ih); + } else { + printf("Step #%d: ERROR! Detected RSA signature, but no MD5 regions\n", Step); + ErrorsUncorrectable++; + } + } + + if(summary && summary<=Step) goto out; + + DEBUG_EXIT_RSA; + + + // + // Main data CRC/checksums if specified + // + printf("\nStep #%d: Reading Main Data CRC/Checksums ..\n", ++Step); + + if(Config.crc[0].r.start==0 && Config.crc[0].r.end==0) + { + FindMainCRCPreBlk(&ih); + } + + if(Config.crc[1].r.start==0 && Config.crc[1].r.end==0) + { + FindMainCRCBlks(&ih); + } + + // note, crc0 and crc4 don't have offsets! + if(Config.crc[1].offset==0) + { + FindMainCRCOffsets(&ih); /* Detect if using CRC algo */ + } + + if(Config.csm_offset==0) + { + FindMainCSMOffsets(&ih); /* Detect if using Checksum algo */ + } + + if(Config.crc[1].r.start && Config.crc[1].r.end && + (Config.crc[1].offset || Config.csm_offset)) { + if(Verbose && Config.csm_offset) { + if(Config.crc[1].offset) { + printf(" %s has both main CRC and checksum offsets!\n", + ih.filename); + } else { + printf("WARNING: %s has no main CRC offset(s) but does have a main checksum offset!\n", + ih.filename); + DoMainCRCs(&ih); + } + } + + /* Note: both CRC and checksum are possible! */ + if(Config.crc[1].offset) + { + DoMainCRCs(&ih); + } + + if(Config.csm_offset) + { + DoMainCSMs(&ih); + } + } + else + { + printf("Step #%d: ERROR! Skipping Main Data checksums ... UNDEFINED\n", + Step); +#ifdef DEBUG_CRC_MATCHING + DoMainCRCs(&ih); + DoMainCSMs(&ih); +#endif + ErrorsUncorrectable++; + } + + if(summary && summary<=Step) goto out; + + DEBUG_EXIT_CRC; + + + // + // ROMSYS Program Pages + // + if(Config.romsys) + { + printf("\nStep #%d: ROMSYS Program Pages\n", ++Step); + DoROMSYS_ProgramPages(&ih); + } + else + { + printf("Step #%d: ERROR! Skipping ROMSYS Program Pages.. UNDEFINED\n", Step); + ErrorsUncorrectable++; + } + + if(summary && summary<=Step) goto out; + + DEBUG_EXIT_ROMSYS_PP; + + + // + // Main program checksums + // + printf("\nStep #%d: Reading Main Program Checksums ..\n", ++Step); + if(Config.main_checksum_offset==0) + { + FindMainProgramOffset(&ih); + } + + if(Config.main_checksum_final==0) + { + FindMainProgramFinal(&ih); + } + + if (Config.main_checksum_offset && Config.main_checksum_final) + { + //DoMainProgramCSM(&ih, Config.main_checksum_offset, Config.main_checksum_final); + DoMainProgramCSM(&ih); + } + else + { + printf("Step #%d: ERROR! Skipping Main Program Checksums.. UNDEFINED\n", Step); + ErrorsUncorrectable++; + } + + if(summary && summary<=Step) goto out; + + DEBUG_EXIT_MAIN; + + + // + // Multi point checksums + // + printf("\nStep #%d: Reading Multipoint Checksum Blocks ..\n", ++Step); + + for (i=0;i<2;i++) { + if(Config.multipoint_block_start[i]==0) + { + FindChecksumBlks(&ih, i); + } + + if(Config.multipoint_block_start[i]) + { + int bootrom=0; + int printed_dots=0; + +#ifdef CHECK_BOOTROM_MP + /* Only check for whitelist in main multipoint block */ + if (i==1) + bootrom = check_whitelist(&ih, Config.multipoint_block_start[i]); +#endif + + /* Images with 2+64 main MP descriptors do not have an end marker */ + for(iTemp=0; iTemp1) bootrom=0; + + memset(&buf, 0, sizeof(buf)); + sbprintf(&buf, "%2d) ",iTemp+1); + result = DoChecksumBlk(&ih, + Config.multipoint_block_start[i]+(Config.multipoint_desc_len*iTemp), + &buf, bootrom); + if (buf.pbuf) { + if (iTemp<3 || result<0 || Verbose>0 || iTemp>MAX_MP_BLOCK_LEN-4) + { + printf("%s", buf.pbuf); + printed_dots=0; + } + else if (!printed_dots) { + printed_dots=1; + printf(" ..........\n"); + } + free (buf.pbuf); + } + + if (result == 1) { break; } // end of blocks; + } + printf(" Multipoint #%d: [%d blocks x <16> = %d bytes]\n", i+1, iTemp, iTemp*16); + } + else + { + if (i!=0) { + printf("Step #%d: ERROR! Skipping Multipoint Checksum Block... UNDEFINED\n", Step); + ErrorsUncorrectable++; + } + } + } + + DEBUG_EXIT_MULTIPOINT; + + /* if (!Config.readonly) */ { + int errs; + printf("\nStep #%d: Looking for rechecks ..\n", ++Step); + if ((errs=ProcessRecordDeps())) { + printf("\n*** WARNING! Unsatisfied rechecks. You may have to rerun ME7Sum on this file!\n"); + ErrorsFound+=errs; + } + } + + // + // All done! + // + printf("\n*** Found %d checksums in %s\n", ChecksumsFound, input); + + if(ErrorsUncorrectable) + { + printf("\n*** ABORTING! %d uncorrectable error(s) in %s! ***\n", ErrorsUncorrectable, input); + return -1; + } + + if(output && ErrorsCorrected > 0) + { + struct strbuf buf; + + memset(&buf, 0, sizeof(buf)); + printf("\nAttempting to output corrected firmware file '%s'\n",output); + // write crc corrected file out + if (ih.pad == PADDING_DOUBLED) { + memcpy(ih.d.u8, ih.d.u8+512*1024, 512*1024); + } + save_file(output,ih.d.p,ih.pad==PADDING_NONE?ih.len:ih.len*2, &buf); + if(buf.pbuf) { + printf("%s", buf.pbuf); + free(buf.pbuf); + } + } + +out: + + // close the file + if(ih.d.p != 0) { ifree_file(&ih); } + + // free config + if(osconfig != 0) { free_properties(osconfig); } + + // Made minor alterations in output to circumvent issue #9 @nyetwurk + if (ErrorsCorrected!=ErrorsFound) { + printf("\n*** WARNING! %d/%d uncorrected error(s) in %s! ***\n", + ErrorsFound-ErrorsCorrected, ErrorsFound, input); + } else if (ErrorsFound == 0 && output){ + printf("\n*** No errors were found and so no \"%s\" was generated.\n", output); + } else if (output) { + printf("\n*** DONE! %d/%d error(s) in %s corrected in %s! ***\n", ErrorsCorrected, + ErrorsFound, input, output); + } else { + printf("\n*** DONE! %d error(s) in %s! ***\n", ErrorsFound, input); + } + + if (ReportFile) { + PrintAllRecords(ReportFile); + fclose(ReportFile); + } + + FreeAllRecords(); + + return 0; +} + +/* + * GetRomInfo + * + * - uses config file to parse rom data and show interesting information about this rom dump + */ + +static int GetRomInfo(const struct ImageHandle *ih, struct section *osconfig) +{ + InfoListItem *info; + int max_len=0; + + if(ih == NULL) return(-1); + + // Find the longest label so we know how big the label column should be + for(info=romInfo; info->attr_type!=END_LIST; info++) + { + if(info->item->off && info->item->len && strlen(info->label) > max_len) { + max_len=strlen(info->label); + } + } + + if (!max_len) { return -1; } + + for(info=romInfo; info->attr_type!=END_LIST; info++) + { + char *str_data; + InfoItem *item=info->item; + if(item->off == 0 || item->len == 0) + { + continue; + } + + if(item->off+item->len >= ih->len) + { + printf("%s = INVALID OFFSET/LEN 0x%x/%d\n",info->label, item->off, item->len); + continue; + } + str_data=malloc(item->len+1); + /* snprintf null terminates for us if string is too long :) */ + snprintf(str_data, item->len+1, "%s", ih->d.s+item->off); // Leave room for null termination + printf(" %-*s : '%s'\n", max_len, info->label, str_data); + free(str_data); + } + return 0; +} + +static int DoRomInfo(const struct ImageHandle *ih, struct section *osconfig) +{ + uint32_t num_of; + int i, max_len=0; + + if(ih == NULL) return(-1); + + GetRomInfo(ih, osconfig); + + if ((num_of = get_property_value(osconfig, "dumps", "dump_show", NULL))<=0) + { + return 0; + } + + // Find the longest label so we know how big the label column should be + for(i=1;i<=num_of;i++) + { + char label_str[81]; + const char * ptr_label; + + snprintf(label_str, sizeof(label_str), "dump_%d_label", i); + ptr_label = get_property(osconfig, "dumps", label_str, NULL); + if(ptr_label) { + if(strlen(ptr_label)>max_len) { + max_len = strlen(ptr_label); + } + ptr_label=NULL; + } + } + + printf("\nROM Dumps:\n"); + + // + // Dynamically walks through the config file and shows all properties defined... + // + for(i=1;i<=num_of;i++) + { + char type_str[81]; + char visible_str[81]; + char label_str[81]; + char offset_str[81]; + char length_str[81]; + +#ifdef DEBUG_ROM_INFO + const char * ptr_type; +#endif + const char * ptr_visible; + const char * ptr_label; + uint32_t ptr_offset; + uint32_t ptr_length; + + snprintf(type_str, sizeof(type_str), "dump_%d_type", i); + snprintf(visible_str,sizeof(visible_str), "dump_%d_visible",i); + snprintf(label_str, sizeof(label_str), "dump_%d_label", i); + snprintf(offset_str, sizeof(offset_str), "dump_%d_offset", i); + snprintf(length_str, sizeof(length_str), "dump_%d_len", i); + + // get config out of ini file... +#ifdef DEBUG_ROM_INFO + ptr_type = get_property( osconfig, "dumps", type_str, NULL); +#endif + ptr_visible = get_property( osconfig, "dumps", visible_str, NULL); + ptr_label = get_property( osconfig, "dumps", label_str, NULL); + ptr_offset = get_property_value( osconfig, "dumps", offset_str, NULL); + ptr_length = get_property_value( osconfig, "dumps", length_str, NULL); + + if(ptr_length == 0) + { + // zero length, skip + } + else if(ptr_offset+ptr_length >= ih->len) + { + printf("%s = INVALID OFFSET/LEN 0x%x/%d\n",ptr_label, ptr_offset, ptr_length); + } + else + { + char str_data[1024]; + // restrict maximum dump to 1kbyte [buffer size] + if(ptr_length > sizeof(str_data) - 1) ptr_length = sizeof(str_data) - 1; // Leave room for null termination + DEBUG_ROM("\n%s = %s\n",type_str, ptr_type); + DEBUG_ROM("%s = %s\n",visible_str, ptr_visible); + DEBUG_ROM("%s = '%s'\n",label_str, ptr_label); + DEBUG_ROM("%s = 0x%x\n",offset_str, ptr_offset); + DEBUG_ROM("%s = %d\n",length_str, ptr_length); + + /* snprintf null terminates for us if string is too long :) */ + snprintf(str_data, sizeof(str_data), "%s", ih->d.s+ptr_offset); + if(! strcmp("true",ptr_visible)) + { + printf(" %-*s : '%s'\n", max_len, ptr_label, str_data); + } + else + { + printf(" %-*s = 'HIDDEN'\n", max_len, ptr_label); + } + } + } + return 0; +} + +/* NEEDLE/HAYSTACK util */ +static int FindData(const struct ImageHandle *ih, const char *what, + const uint8_t *n, const uint8_t *m, int len, // needle, mask, len of needle/mask + int off_l, int off_h, // where to find hi/lo (short word offset into find array) + uint32_t *offset, size_t offset_len, // array to store discovered offsets, len of array + uint32_t *where) // address of match (ONLY if single match), NULL if not needed +{ + /* Note that off_l and off_h are SHORT WORD offsets, i.e. 1 == 2 bytes */ + + int i, found=0; + uint32_t last_where=0; + + assert((len&1)==0); // make sure its even + + for(i=0;i+lenlen;i+=2) + { + i=search_image(ih, i, n, m, len, 2); + if (i<0) break; + else { + int high_shift=16; + uint16_t low=le16toh(ih->d.u16[i/2+off_l]); + uint16_t high=le16toh(ih->d.u16[i/2+off_h]); + uint32_t addr; + + /* maybe segment address */ + if (high&0xfe00) high_shift=14; + + addr=(high<1) { + printf(" Found possible %s #%d at 0x%x (from 0x%x)\n", + what, found+1, addr, i); + } + + if (addr>Config.base_address && addr-Config.base_addresslen) { + if (Verbose>2) { + hexdump(ih->d.u8+i-4, 4, " ["); + hexdump(ih->d.u8+i, len, "] "); + hexdump(ih->d.u8+i+1, 4, "\n"); + } + + if(found1) { + printf(" %s #%d at 0x%x (from 0x%x) out of range\n", + what, found+1, addr, i); + } + } + } + if (found==1 && where) *where=last_where; + return found; +} + +// +// Calculate the Bosch Motronic ME71 checksum for the given range +// +static uint32_t CalcChecksumBlk8(const struct ImageHandle *ih, const struct Range *r) +{ + uint32_t nChecksum = 0, nIndex; + + for(nIndex = r->start; nIndex <= r->end; nIndex++) + { + nChecksum+=le16toh(ih->d.u8[nIndex]); + } + + return nChecksum; +} + +static uint32_t CalcChecksumBlk16(const struct ImageHandle *ih, const struct Range *r) +{ + uint32_t nChecksum = 0, nIndex; + + for(nIndex = r->start/2; nIndex <= r->end/2; nIndex++) + { + nChecksum+=le16toh(ih->d.u16[nIndex]); + } + + return nChecksum; +} + +static int NormalizeRange(const struct ImageHandle *ih, struct Range *r) +{ + // special case: leave end markers alone + if (r->start==0xffffffff && r->end==0xffffffff) return 0; + + // We are only reading the ROM. Therefore the start address must be + // after Config.base_address. Ignore addresses lower than this and + // remove the offset for addresses we're interested in. + if (r->start < Config.base_address || r->end < Config.base_address) + { + // The checksum block is outside our range + printf(" ERROR: INVALID STARTADDDR/ENDADDR 0x%x/0x%x is less than base address 0x%x\n", + r->start, r->end, Config.base_address); + return -1; + } + + r->start -= Config.base_address; + r->end -= Config.base_address; + + if(r->start>r->end) + { + // start is after end! + printf(" ERROR: INVALID STARTADDDR/ENDADDR: 0x%x>0x%x\n", r->start, r->end); + return -1; + } + + if(r->start>=ih->len || r->end>=ih->len) + { + // The checksum block is outside our range + printf(" ERROR: INVALID STARTADDDR/ENDADDR: 0x%x/0x%x is past 0x%x\n", r->start, r->end, (int)ih->len); + return -1; + } + + return 0; +} + +/* Actual work */ +static int FindEPK(const struct ImageHandle *ih) +{ + // LL LL HH? + static const uint8_t n[]={0x43, 0xF8, 0x00, 0x00, 0x9d, 0x07, 0x09, 0x80}; + static const uint8_t m[]={0xf3, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0}; + int i, off=0, high, low, found=0; + int max = 0x30000; + const char *start; + int len=0; + int ret=-1; + + printf(" Searching for EPK signature..."); + + for(i=0;imax) break; + low = le16toh(ih->d.u16[i/2+1]); + high = le16toh(ih->d.u16[i/2+3])>>8; // ?? + off = (high<<16) | low; + if (off Config.base_address+ih->len) { + printf(" ERROR: INVALID ADDR 0x%x\n", off); + break; + } + off -= Config.base_address; + if (Verbose) { + printf( "%s: possible EPK @0x%x, ASM @0x%x\n", ih->filename, off, i); + if (Verbose>1) { + hexdump(ih->d.u8+i-4, 4, "["); + hexdump(ih->d.u8+i, sizeof(n), "]"); + hexdump(ih->d.u8+i+sizeof(n), 4, "\n\n"); + hexdump(ih->d.u8+off, 0x40, "\n"); + } + } + found++; + } + + if (found==1) { + ret=0; + } else { + static const char sig[]={0xc3, 0x3c, 0x5a, 0x5a, 0xff, 0xff}; + i=0x10000-2; + if (memcmp(ih->d.u8+i, sig, sizeof(sig))==0) { + off=i+6; + if (Verbose) { + printf(" %s: found EPK @0x%x, sig 0x%x\n", ih->filename, off, i); + if (Verbose>1) { + hexdump(ih->d.u8+i, 6, "\n\n"); + hexdump(ih->d.u8+i+6, 0x40, "\n"); + } + } + ret=0; + } else { + off=0; + } + } + + if (ret) { + printf("missing\n"); + return ret; + } + + start = ih->d.s+off+1; + + if(start[1]==0x0a) start+=2; + + for(len=1;len<0x40;len++) { + if (start[len-1]=='/' && start[len]==(char)0xff) break; + } + + if(len>=0x40) { + printf("missing\n"); + return -1; + } + + InfoConfig.EPK.off=start-ih->d.s; + InfoConfig.EPK.len=len; + + printf("OK\n"); + return 0; +} + +struct string_desc { + uint8_t tag; + uint8_t len; + uint16_t ptr; + uint16_t seg; +}; + +static int getInfoItem(const struct ImageHandle *ih, InfoItem *ii, const struct string_desc *d) +{ + int ptr = le16toh(d->ptr); + int seg = le16toh(d->seg); + int addr = (seg<<14) | ptr; + if(d->tag==6) { + if(addr>Config.base_address && addr+d->lenlen) { + ii->off=addr-Config.base_address; + ii->len=d->len; + return d->len; + } + } + return -1; +} + +static int dump_string_desc(const struct ImageHandle *ih, const struct string_desc *d) +{ + struct InfoItem ii={0,0}; + char buf[257]; + int ret = getInfoItem(ih, &ii, d); + + if (ret<0) return -1; + + if (ii.len) { + snprintf(buf, ii.len+1, "%s", ih->d.s+ii.off); + printf("%d: '%s'\n", ret, buf); + } + + return 0; +} + +static int FindECUID(const struct ImageHandle *ih) +{ + int found; + uint32_t offset[2]={0,0}; + uint32_t where=0; + // E6 F4 .. .. E6 F5 06 02 F6 F4 42 E2 F6 F5 44 E2 + // E6 F4 .. .. E6 F5 06 02 F6 F4 40 E2 F6 F5 42 E2 + // \e6f4..e6f50602f6f4.e2f6f5.e2 + // LL LL HH HH + uint8_t needle[] = {0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x06, 0x02, 0xF6, 0xF4, 0x42, 0xE2, 0xF6, 0xF5, 0x44, 0xE2}; + uint8_t mask[] = {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xf0, 0xff}; + + printf(" Searching for ECUID table..."); + + found=FindData(ih, "ECUID table", needle, mask, sizeof(needle), 1, 3, offset, 2, &where); + + if (found>0) + { + int i; + const struct string_desc *d0=(struct string_desc *)(ih->d.u8+offset[0]); + const struct string_desc *d1=(struct string_desc *)(ih->d.u8+offset[1]); + if (Verbose>2) { + for(i=0; i<30; i++) { + if (d0[i].tag==6) { + printf("0 %d:", i); + dump_string_desc(ih, d0+i); + printf("\n"); + } + } + if (found>1) { + for(i=0; i<30; i++) { + if (d1[i].tag==6) { + printf("1 %d:", i); + dump_string_desc(ih, d1+i); + printf("\n"); + } + } + } + } + if (getInfoItem(ih, &InfoConfig.hw_number, d0+2)<=0 && found>1) { + d0=(const struct string_desc *)(ih->d.u8+offset[1]); + d1=(const struct string_desc *)(ih->d.u8+offset[0]); + getInfoItem(ih, &InfoConfig.hw_number, d0+2); + } + /* + dump_string_desc(ih, d0+4); + dump_string_desc(ih, d0+10); + dump_string_desc(ih, d0+11); + dump_string_desc(ih, d0+19); + */ + getInfoItem(ih, &InfoConfig.sw_number, d0+4); + getInfoItem(ih, &InfoConfig.part_number, d0+10); + getInfoItem(ih, &InfoConfig.sw_version, d0+11); + getInfoItem(ih, &InfoConfig.engine_id, d0+19); + //if(found>1) + // getInfoItem(ih, &InfoConfig.HW_MAN, d1+1); + printf("OK\n"); + return 0; + } + + if (found>1) + { + printf("Too many matches (%d). ECUID table find failed\n", found); + } + + printf("%d matches, missing\n", found); + return 0; +} + +static int FindRomInfo(const struct ImageHandle *ih) +{ + int ret=0; + ret+=FindEPK(ih); + ret+=FindECUID(ih); + return ret; +} + +static int FindRSAOffsets(struct ImageHandle *ih) +{ + int s=0,n=0,e=0; + int exponent=0; + int i; + int ret=0; + static const uint8_t needle[2][14] = { + // LL LL HH HH + {0x80, 0x00, 0x88, 0x40, 0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x80, 0x00, 0x88, 0x50}, + {0xE0, 0x44, 0x88, 0x40, 0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x80, 0x00, 0x88, 0x50} + }; + static const uint8_t mask[] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff}; + + for(i=0;i<2;i++) { + int found; + uint32_t offset[2]={0,0}; + uint32_t where=0; + + printf(" Searching for RSA offset #%d...", i); + found=FindData(ih, "RSA offset", needle[i], mask, sizeof(needle[i]), 3, 5, offset, 2, &where); + + if (found==(i?1:2)) + { + DEBUG_RSA(" Found RSA offset[0] #%d 0x%x\n", i, offset[0]); + + if (i==0) { + DEBUG_RSA(" Found RSA offset[1] #%d 0x%x\n", i, offset[1]); + s=offset[0]; + n=offset[1]; + } else { + e=offset[0]; + } + + printf("OK\n"); + continue; + } + + if (found>(i?1:2)) + { + DEBUG_RSA("%d: Too many matches (%d). RSA find failed\n", i, found); + continue; + } + + printf("missing\n"); + ret=-1; + } + + if (ret) return ret; + + if (s+RSA_BLOCK_SIZE>=ih->len) return -1; + if (n+RSA_BLOCK_SIZE>=ih->len) return -1; + if (e+4+RSA_BLOCK_SIZE>=ih->len) return -1; + + exponent=ntohl(*(uint32_t*)(ih->d.u8+e)); + + if (exponent!=3) return -1; + + Config.rsa.s=s; + Config.rsa.n=n; + Config.rsa.e=e; + Config.rsa.ds=e+4; + Config.rsa.exponent=exponent; + + printf(" Signature: @%x-%x\n", s, s+RSA_BLOCK_SIZE); + printf(" Modulus: @%x-%x\n", n, n+RSA_BLOCK_SIZE); + printf(" Exponent: @%x = %d\n", e, exponent); + if (Verbose) { + printf(" Default Signature: @%x-%x\n", e+4, e+4+RSA_BLOCK_SIZE); + } + + return 0; +} + +static int FindMD5Ranges(struct ImageHandle *ih) +{ + // r LL LL + uint8_t needle[] = + {0xE1, 0x08, 0xF7, 0xF8, 0x00, 0xF0, 0xF2, 0xF4, 0x00, 0x00, 0xF2, 0xF5, 0x00, 0x00, 0xF6, 0xF4}; + uint8_t mask[] = + {0xff, 0xcf, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff}; + + int found=0, i=0; + int addr=-1; + int table=0, count=0; + + printf(" Searching for MD5 ranges..."); + for(i=0;i+sizeof(needle)+2len;i+=2) { + i=search_image(ih, i, needle, mask, sizeof(needle), 2); + if (i<0) break; + found++; + DEBUG_RSA(" Found possible MD5 ASM #%d @0x%x\n", found, i); + addr=i; + } + + if (found!=1) { + printf("missing\n"); + return -1; + } else { + uint8_t *p = ih->d.u8+addr; + uint16_t *p16 = ih->d.u16+(addr/2); + + count = ((p[1]&0xf0)>>4)+1; + /* FIXME: hardcoded HH HH to 0x0081xxxx? */ + table =le16toh(p16[4])|0x10000; + // printf("MD5 arg2 0x%04x\n", le16toh(p16[6])); + + DEBUG_RSA(" Found MD5 ASM @0x%x (table=%x, count=%d)\n", addr, table, + count); + if(count>0 && count<=MD5_MAX_BLKS) { + uint32_t buf[MD5_MAX_BLKS*2]; + memcpy_from_le32(buf, ih->d.u8+table, sizeof(buf)); + for (i=0;ilen) { + printf("size %d>len %d\n", (int)size, len); + return -1; + } + + /* pad with zeros */ + if (off>0) memset(buf, 0, off); + + mpz_export(buf+off, &size, 1, 1, 0, 0, x); + + return size; +} + +static int rsa_block_pad(uint8_t *blk, const uint8_t *data, int len) +{ + if (len+3>RSA_BLOCK_SIZE) { + if (Verbose) + printf("Data too long %d+3>%d\n", len, RSA_BLOCK_SIZE); + return -1; + } + + blk[0]=0; + blk[1]=1; + memset(blk+2, 0xff, RSA_BLOCK_SIZE-2-len-1); + blk[RSA_BLOCK_SIZE-len-1]=0; + memcpy(blk+RSA_BLOCK_SIZE-len, data, len); + return 0; +} + +static int rsa_block_unpad(uint8_t *data, int len, const uint8_t *blk) +{ + int i; + + /* expect 00 01 prefix */ + if(blk[0]!=0x00 || blk[1]!=0x01) { + if (Verbose>1) + printf("bad prefix [%x %x]!\n", blk[0], blk[1]); + return 0; + } + + for(i=2;blk[i] && i1) { + printf("\n"); + printf("---------------Private Key-----------------\n"); + printf("kp.n is [%s]\n", mpz_get_str(NULL, 16, kp.n)); + printf("kp.e is [%s]\n", mpz_get_str(NULL, 16, kp.e)); + printf("---------------Public Key------------------\n"); + printf("ku.n is [%s]\n", mpz_get_str(NULL, 16, ku.n)); + printf("ku.e is [%s]\n", mpz_get_str(NULL, 16, ku.e)); + printf("ku.d is [%s]\n", mpz_get_str(NULL, 16, ku.d)); + printf("ku.p is [%s]\n", mpz_get_str(NULL, 16, ku.p)); + printf("ku.q is [%s]\n", mpz_get_str(NULL, 16, ku.q)); + } + + /* put new modulus in place */ + memset(n, 0, sizeof(n)); + mpz_export_buf(n, sizeof(n), kp.n); + if (Verbose>1) { + printf("new n is:\n"); + hexdump(msg, RSA_BLOCK_SIZE, "\n"); + } + memcpy(ih->d.u8+Config.rsa.n, n, RSA_BLOCK_SIZE); + + /* recalc MD5 */ + MD5_Init(&ctx); + for(i=0;i0) { + MD5_Update(&ctx, ih->d.u8+Config.rsa.md5[i].start, len); + } + } + MD5_Final(calc_md5, &ctx); + + /* pad msg, append md5 */ + rsa_block_pad(msg, calc_md5, 16); + + /* setup decryption */ + mpz_init(C); + mpz_init(M); + mpz_import(C, sizeof(msg), 1, 1, 0, 0, msg); + block_decrypt(M, C, ku); + + memset(sig, 0, sizeof(sig)); + mpz_export_buf(sig, sizeof(sig), M); + + if (Verbose>1) { + printf("padded md5 is:\n"); + hexdump(msg, RSA_BLOCK_SIZE, "\n"); + printf("new sig is:\n"); + hexdump(sig, RSA_BLOCK_SIZE, "\n"); + } + + /* verify that the signature will generate the new MD5 with new pub key */ + block_encrypt(C, M, kp); + memset(nmsg, 0, sizeof(nmsg)); + mpz_export_buf(nmsg, sizeof(nmsg), C); + + if(Verbose>1) { + printf("new padded md5 is:\n"); + hexdump(nmsg, RSA_BLOCK_SIZE, "\n"); + } + + if(memcmp(msg, nmsg, sizeof(msg))==0) { + memcpy(ih->d.u8+Config.rsa.s, sig, RSA_BLOCK_SIZE); + } else { + printf("padded md5 is:\n"); + hexdump(msg, RSA_BLOCK_SIZE, "\n"); + printf("new padded md5 is:\n"); + hexdump(nmsg, RSA_BLOCK_SIZE, "\n"); + printf("FAILED\n"); + ret=-1; + } + + mpz_clear(C); + mpz_clear(M); + +out: + mpz_clear(kp.n); + mpz_clear(kp.e); + mpz_clear(ku.n); + mpz_clear(ku.e); + mpz_clear(ku.d); + mpz_clear(ku.p); + mpz_clear(ku.q); + + return ret; +} + +static int DoRSA(struct ImageHandle *ih) +{ + public_key kp; + mpz_t M, DM, C, DC; + uint8_t buf[RSA_BLOCK_SIZE]; + uint8_t dbuf[RSA_BLOCK_SIZE]; + uint8_t md5[16]; + uint8_t dmd5[16]; + uint8_t calc_md5[16]; + MD5_CTX ctx; + int i; + + struct ReportRecord *rrn = CreateRecord("RSA mod", Config.rsa.n, RSA_BLOCK_SIZE); + struct ReportRecord *rrs = CreateRecord("RSA sig", Config.rsa.s, RSA_BLOCK_SIZE); + + memset(md5, 0, sizeof(md5)); + memset(dmd5, 0, sizeof(dmd5)); + memset(calc_md5, 0, sizeof(calc_md5)); + + mpz_init(kp.n); + mpz_init(kp.e); + mpz_init(M); + mpz_init(DM); + mpz_init(C); + mpz_init(DC); + + mpz_import(kp.n, RSA_BLOCK_SIZE, 1, 1, 0, 0, ih->d.u8+Config.rsa.n); + mpz_set_ui(kp.e, Config.rsa.exponent); + mpz_import(M, RSA_BLOCK_SIZE, 1, 1, 0, 0, ih->d.u8+Config.rsa.s); + mpz_import(DM, RSA_BLOCK_SIZE, 1, 1, 0, 0, ih->d.u8+Config.rsa.ds); + + block_encrypt(C, M, kp); + block_encrypt(DC, DM, kp); + + if (Verbose>1) { + printf("modulus:\n"); + hexdump(ih->d.u8+Config.rsa.n, RSA_BLOCK_SIZE, "\n"); + printf("signature:\n"); + hexdump(ih->d.u8+Config.rsa.s, RSA_BLOCK_SIZE, "\n"); + } + + memset(buf, 0, sizeof(buf)); + memset(dbuf, 0, sizeof(dbuf)); + + mpz_export_buf(buf, sizeof(buf), C); + mpz_export_buf(dbuf, sizeof(dbuf), DC); + + mpz_clear(kp.n); + mpz_clear(kp.e); + mpz_clear(M); + mpz_clear(DM); + mpz_clear(C); + mpz_clear(DC); + + if (Verbose>1) { + printf("sig->padded MD5:\n"); + hexdump(buf, RSA_BLOCK_SIZE, "\n"); + printf("defsig->padded MD5:\n"); + hexdump(dbuf, RSA_BLOCK_SIZE, "\n"); + } + + ChecksumsFound ++; + + MD5_Init(&ctx); + for(i=0;i0) { + AddRange(rrn, Config.rsa.md5+i); + AddRange(rrs, Config.rsa.md5+i); + printf(" %d) 0x%08X-0x%08X\n", i+1, + Config.rsa.md5[i].start, + Config.rsa.md5[i].end); + MD5_Update(&ctx, ih->d.u8+Config.rsa.md5[i].start, len); + } + } + + MD5_Final(calc_md5, &ctx); + + /* + printf("DEncrMD5: "); + if (rsa_block_unpad(dmd5, 16, dbuf)) + ErrorsUncorrectable++; + else + hexdump(dmd5, 16, "\n"); + */ + + if (rsa_block_unpad(md5, 16, buf)) + ErrorsUncorrectable++; + else { + printf(" EncrMD5: "); + hexdump(md5, 16, "\n"); + } + + printf(" CalcMD5: "); + hexdump(calc_md5, 16, "\n"); + + if (memcmp(md5, calc_md5, 16)) { + ErrorsFound++; + if (Config.readonly) + { + printf(" @%x-%x sig ** NOT OK **\n", Config.rsa.s, Config.rsa.s+RSA_BLOCK_SIZE); + printf(" @%x-%x mod ** NOT OK **\n", Config.rsa.n, Config.rsa.n+RSA_BLOCK_SIZE); + return -1; + } + else + { + if (RSASign(ih)) { + ErrorsUncorrectable++; + printf(" ** UNFIXABLE **\n"); + } else { + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } + } + } + else + { + printf(" OK\n"); + } + + return 0; +} + +static int FindROMSYS(struct ImageHandle *ih) +{ + /* autodetect? */ + /* verify stuff is in range? */ + Config.romsys=0x8000; + return 0; +} + +struct ROMSYSDescriptor { + uint32_t res00_0F[4]; /* +0x00-0x0F */ + + uint32_t all_param_sum_p; /* +0x10 */ + uint32_t res14_1F[3]; /* +0x14-0x1F */ + + uint32_t res20_2F[4]; /* +0x20-0x2F */ + + struct Range all_param; /* +0x30-0x37 */ + uint32_t startup_sum; /* +0x38 */ + uint32_t program_pages_csum; /* +0x3C */ +}; + +static int DoROMSYS_Startup(struct ImageHandle *ih, const struct ROMSYSDescriptor *desc) +{ + uint16_t *r16[2]; + uint32_t nCalcStartupSum; + int off = Config.romsys + offsetof(struct ROMSYSDescriptor, startup_sum); + + struct ReportRecord *rr = CreateRecord("ROMSYS Startup", off, 3); + AddRangeStartLength(rr, 0x8000, 2); + AddRangeStartLength(rr, 0xFFFE, 2); + + r16[0]=(uint16_t *)(ih->d.u8 + 0x8000); + r16[1]=(uint16_t *)(ih->d.u8 + 0xFFFE); + nCalcStartupSum = le16toh(*r16[0])+le16toh(*r16[1]); + + printf(" Startup section: word[0x008000]+word[0x00FFFE]\n"); + printf(" @%05x Add=0x%08X CalcAdd=0x%08X", off, + nCalcStartupSum, desc->startup_sum); + + ChecksumsFound ++; + + if (nCalcStartupSum != desc->startup_sum) + { + ErrorsFound++; + if (Config.readonly) + { + printf(" ** NOT OK **\n"); + return -1; + } + else + { + uint16_t *p16 = (uint16_t *)(ih->d.u8 + off); + *p16=le16toh(nCalcStartupSum); + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } + } + else + { + printf(" ADD OK\n"); + } + + return 0; +} + +static uint32_t ProgramPageSum(struct ImageHandle *ih, const struct Range *r, struct ReportRecord *rr) +{ + uint32_t sum=0; + int addr; + for(addr=r->start;addrend;addr+=8*1024) { + uint16_t *p16[2]; + p16[0]=(uint16_t *)(ih->d.u8+addr); /* first word of page */ + AddRangeStartLength(rr, addr, 2); + p16[1]=(uint16_t *)(ih->d.u8+addr+8*1024-2); /* last word of page */ + AddRangeStartLength(rr, addr+8*1024-2, 2); + if (Verbose>4) + printf(" word[0x%06X]+word[0x%06X]\n", + addr, addr+8*1024-2); + sum+=le16toh(*p16[0]) + le16toh(*p16[1]); + } + return sum; +} + +static int DoROMSYS_ProgramPages(struct ImageHandle *ih) +{ + uint32_t nCalcProgramPagesSum; + struct Range r; + int off = Config.romsys + offsetof(struct ROMSYSDescriptor, program_pages_csum); + uint32_t *p32 = (uint32_t *)(ih->d.u8 + off); + struct ReportRecord *rr; + + printf(" Program pages: 8k page first+last in 0x0000-0xFFFF and 0x20000-0x%X\n", + (int)ih->len-1); + + rr = CreateRecord("ROMSYS ProgramPages", off, 4); + + r.start=0x00000; r.end=0x0FFFF; + nCalcProgramPagesSum=ProgramPageSum(ih, &r, rr); + + r.start=0x20000; r.end=ih->len-1; + nCalcProgramPagesSum+=ProgramPageSum(ih, &r, rr); + + printf(" @%06x Add=0x%06X CalcAdd=0x%06X", off, nCalcProgramPagesSum, *p32); + + ChecksumsFound ++; + + if (nCalcProgramPagesSum != *p32) + { + ErrorsFound++; + if (Config.readonly) + { + printf(" ** NOT OK **\n"); + return -1; + } + else + { + *p32=le32toh(nCalcProgramPagesSum); + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } + } + else + { + printf(" ADD OK\n"); + } + + return 0; +} + +static int DoROMSYS_ParamPage(struct ImageHandle *ih, struct ROMSYSDescriptor *desc) +{ + uint16_t *r16[2]; + uint32_t *p32; + int off; + uint32_t nAllParamSum, nCalcAllParamSum; + + struct ReportRecord *rr; + + if(desc->all_param_sum_pall_param_sum_p-Config.base_address>=ih->len) { + printf(" ERROR: INVALID ADDR 0x%x\n", desc->all_param_sum_p); + return -1; + } + + off = desc->all_param_sum_p-Config.base_address; + rr = CreateRecord("ROMSYS ParamPage", off, 4); + + p32 = (uint32_t *)(ih->d.u8 + off); + nAllParamSum=le32toh(*p32); + + NormalizeRange(ih, &desc->all_param); + + AddRangeStartLength(rr, desc->all_param.start, 2); + AddRangeStartLength(rr, desc->all_param.end, 2); + + r16[0]=(uint16_t *)(ih->d.u8 + desc->all_param.start); + r16[1]=(uint16_t *)(ih->d.u8 + desc->all_param.end); + nCalcAllParamSum = le16toh(*r16[0])+le16toh(*r16[1]); + + printf(" All param page: word[0x%06X]+word[0x%06X]\n", + desc->all_param.start, desc->all_param.end); + printf(" @%06x Add=0x%06X CalcAdd=0x%06X", off, + nAllParamSum, nCalcAllParamSum); + + ChecksumsFound ++; + + if (nCalcAllParamSum != nAllParamSum) + { + ErrorsFound++; + if (Config.readonly) + { + printf(" ** NOT OK **\n"); + return -1; + } + else + { + *p32=le32toh(nCalcAllParamSum); + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } + } + else + { + printf(" ADD OK\n"); + } + + return 0; +} + +static int DoROMSYS(struct ImageHandle *ih) +{ + struct ROMSYSDescriptor desc; + int result = 0; + + if (ih->d.u16[0]==0) { + printf(" ** ERROR! First word is zero... corrupted bin? **\n"); + ErrorsUncorrectable++; + } + + memcpy_from_le32(&desc, ih->d.u8+Config.romsys, sizeof(desc)); + + DEBUG_ROMSYS("00 0x%08X 0x%08X 0x%08X 0x%08X\n", + desc.res00_0F[0], desc.res00_0F[1], + desc.res00_0F[2], desc.res00_0F[3]); + + DEBUG_ROMSYS("allparam csum @0x%08X\n", desc.all_param_sum_p); + + DEBUG_ROMSYS("14 0x%08X 0x%08X 0x%08X\n", + desc.res14_1F[0], desc.res14_1F[1], + desc.res14_1F[2]); + + DEBUG_ROMSYS("20 0x%08X 0x%08X 0x%08X 0x%08X\n", + desc.res20_2F[0], desc.res20_2F[1], + desc.res20_2F[2], desc.res20_2F[3]); + + DEBUG_ROMSYS("allparam first/last: 0x%08X, 0x%08X\n", + desc.all_param.start, desc.all_param.end); + + DEBUG_ROMSYS("startup_sum %08X\n", desc.startup_sum); + + DEBUG_ROMSYS("program_pages_csum %08X\n", desc.program_pages_csum); + + result |= DoROMSYS_Startup(ih, &desc); + result |= DoROMSYS_ParamPage(ih, &desc); + + return result; +} + +static int crc_table_fallback(const struct ImageHandle *ih, uint32_t *off) +{ + uint8_t needle[16]; + int i; + int found=0; + + memcpy_to_le32(needle, crc32_tab, sizeof(needle)); + + for(i=0;i+sizeof(needle)len;i+=2) + { + i=search_image(ih, i, needle, NULL, sizeof(needle), 2); + if (i<0) break; + else { + if (Verbose>1) { + printf(" Found possible CRC table #%d @0x%06x\n", found+1, i); + } + if(found<2) off[found]=i; + found++; + } + } + return found; +} + +static int locate_helper(const struct ImageHandle *ih, uint32_t addr) +{ + uint8_t needle[6]={0,0,0,0,0,0}; + uint8_t mask[6]={0xff, 0xff, 0x00, 0x00, 0xff, 0xff}; + int i,found=0; + + addr+=Config.base_address; + + needle[0] = addr&0xff; + needle[1] = (addr>>8)&0xff; + needle[4] = (addr>>16)&0xff; + needle[5] = (addr>>24)&0xff; + + for(i=0;i+sizeof(needle)len;i+=2) + { + i=search_image(ih, i, needle, mask, sizeof(needle), 2); + if (i<0) break; + printf("ref #%d %08X @0x%06x\n", ++found, addr, i); + hexdump(ih->d.u8+i-8, 8, " ["); + hexdump(ih->d.u8+i, 2, "] "); + hexdump(ih->d.u8+i+2, 2, " ["); + hexdump(ih->d.u8+i+4, 2, "] "); + hexdump(ih->d.u8+i+6, 8, "\n"); + } + + return 0; +} + +static int FindCRCTab(const struct ImageHandle *ih) +{ + uint32_t off[2]={0,0}; + int i, found=0; + uint32_t where=0; + + + // E6 F4 02 D8 E6 F5 81 00 A9 60 C0 62 5C 22 + // E6 F4 6A E7 E6 F5 81 00 A9 60 C0 62 5C 22 + // e6 f4 5a 77 e6 f5 82 00 a9 60 c0 62 5c 22 + + // E6 F4 A6 DF E6 F5 81 00 C0 C2 5C 22 + // E6 F4 52 DB E6 f5 81 00 C0 C2 5C 22 + // e6 f4 32 b5 e6 f5 81 00 c0 c2 5c 22 + // e6 f4 28 dc e6 f5 81 00 c0 c2 5c 22 + + static const uint8_t + // LL LL HH HH + needle0[]={0xe6,0xf4,0x00,0x00,0xe6,0xf5,0x80,0x00,0xa9,0x60,0xc0,0x62,0x5c,0x22}, + mask0[]={0xff,0xff,0x01,0x00,0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + + needle1[]={0xe6,0xf4,0x00,0x00,0xe6,0xf5,0x80,0x00,0xc0,0xc2,0x5c,0x22}, + mask1[]={0xff,0xff,0x01,0x00,0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff}; + + + printf(" Searching for CRC table(s)..."); + DEBUG_FLUSH_CRC; + + found=FindData(ih, "CRC table", needle0, mask0, sizeof(needle0), 1, 3, off, 2, &where); + + if (found<1 || found>2) + found=FindData(ih, "CRC table", needle1, mask1, sizeof(needle1), 1, 3, off, 2, &where); + + if (found<1 || found>2) { + printf("missing\n"); + } else { + int temp=found; + found=0; + for (i=0;id.u8+off[i]))); + if(crc0!=0) { + printf("*** WARNING: ASM detect @0x%06x, CRC[0]=%08X in %s\n", + off[i], crc0, ih->filename); + continue; + } + Config.crctab[found++]=off[i]; + } + } + + if (found<1 || found>2) { + int temp = crc_table_fallback(ih, off); + printf(" Searching for CRC table(s) using fallback..."); + if (temp<1 || temp>2) { + printf("UNDEFINED\n"); + return -1; + } + + for (i=0;ifilename); + } + + printf("OK\n"); + return 0; +} + +static int DoCRCTab(struct ImageHandle *ih) +{ + uint8_t letab[1024]; + int i; -/* - * main() - * - */ + assert(sizeof(letab)==sizeof(crc32_tab)); -int main(int argc, char **argv) + memcpy_to_le32(letab, crc32_tab, sizeof(letab)); + + for(i=0;i<2;i++) { + if(!Config.crctab[i]) continue; + if(memcmp(ih->d.u8+Config.crctab[i], letab, sizeof(letab))) { + printf(" CRC table #%d: ", i); + ErrorsFound++; + if(Verbose>2) { + hexdump(ih->d.u8+Config.crctab[i], 1024, "\n"); + hexdump(letab, 1024, "\n"); + } + if (Config.readonly) + { + printf(" ** NOT OK - TUNER MODIFIED? **\n"); + return -1; + } + memcpy(ih->d.u8+Config.crctab[i], letab, sizeof(letab)); + ErrorsCorrected++; + printf(" ** FIXED - WARNING: REVERTED TUNER MODIFICATION! **\n"); + } + } + + printf(" CRC table(s) OK\n"); + return 0; +} + +static int FindMainCRCPreBlk(const struct ImageHandle *ih) { - int iTemp; - int result; - int num_of; - struct ImageHandle ih; - struct section *osconfig; + int found; + uint32_t offset=0; + uint32_t where=0; + // LL LL HH HH s + uint8_t needle[] = {0xE6, 0xFC, 0x00, 0x00, 0xE6, 0xFD, 0x80, 0x00, 0xE0, 0x0E, 0xDA, 0x00, 0x00, 0x00, 0xF6, 0xF4}; + uint8_t mask[] = {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff}; - // information about the tool - printf("ME7Tool [ Management tool for Bosch ME7.x firmwares]\n"); - printf("Inspiration from Andy Whittaker's tools and information\n"); - printf("Written by 360trev and nyet [BSD License Open Source]. \n\n"); + printf(" Searching for main data CRC pre block..."); + DEBUG_FLUSH_CRC; - if(argc < 4) + found=FindData(ih, "CRC pre block", needle, mask, sizeof(needle), 1, 3, &offset, 1, &where); + + if (found==1) { - printf("Usage: %s \n",argv[0]); - return -1; + // crc0 is reserved for pre-region + Config.crc[0].r.start=offset; + Config.crc[0].r.end=offset+(ih->d.u8[where+9]>>4)-1; // s + DEBUG_CRC("Found %s #%d 0x%x-0x%x (0x%x): ", "CRC pre block", 0, offset, Config.crc[0].r.end, where); + + printf("OK\n"); + return 0; } - printf("Attemping to open firmware config file %s\n",argv[3]); - // load properties file into memory - osconfig = read_properties(argv[3]); - if(osconfig == NULL) + if (found>1) { - printf("failed to open config file\n"); - return -1; + DEBUG_CRC("Too many matches (%d). CRC/csum block start find failed\n", found); } - // get rom region information from config file (see defined property list) - result = process_properties_list(osconfig, romProps); + printf("missing\n"); + return 0; +} - // open the firmware file - printf("\nAttemping to open firmware file %s\n",argv[1]); - if (iload_file(&ih, argv[1], Config.readonly?0:1)) - { - printf("failed to open firmware file\n"); - goto out; - } +static int FindMainCRCBlks(const struct ImageHandle *ih) +{ + int i, found, ret0=-1, ret1=-1; + uint32_t offset[MAX_CRC_BLKS]; + // LL LL HH HH + uint8_t n0[] = {0xE6, 0xF8, 0x00, 0x00, 0xE6, 0xF9, 0x80, 0x00, 0xF2, 0xF4 /*, 0x00, 0x00, 0x24, 0x8F */}; + uint8_t m0[] = {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff /*, 0x00, 0x00, 0xff, 0xff */}; + // LL LL HH HH + uint8_t n1[] = {0x10, 0x9B, 0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x80, 0x00 /*, 0x26, 0xF4, 0x9B, 0xE6 */}; + uint8_t m1[] = {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xff /*, 0xff, 0xff, 0xff, 0xff */}; - // sanity check: validate firmware file is at least 512kbytes length before proceeding. - if(ih.len < (1024*512)) { - printf("File too small. Are you sure this is a firmware dump?\n"); - goto out; - } + printf(" Searching for main data CRC/csum blocks..."); + DEBUG_FLUSH_CRC; - // - // Step #0 Show interesting ROM information - // - if ((num_of = get_property_value(osconfig, "dumps", "dump_show", NULL))>0) - { - printf("\nStep #0: Showing ROM info (typically ECUID Table)\n\n"); - result = GetRomInfo(&ih, osconfig, num_of); - } - else + found=FindData(ih, "CRC/csum block starts", n0, m0, sizeof(n0), 1, 3, offset, MAX_CRC_BLKS, NULL); + + if (found>0 && found<=MAX_CRC_BLKS) { - printf("\nStep #0: Skipping ROM info... undefined\n"); + for (i=0;iMAX_CRC_BLKS) { - printf("\nStep #1: Skipping main ROM CRCs... undefined\n"); + DEBUG_CRC("Too many matches (%d). CRC/csum block start find failed\n", found); } - // - // Step #2 Main ROM checksums - // - printf("\nStep #2: Reading main ROM checksum...\n"); - DoMainChecksum(&ih); + found=FindData(ih, "CRC/csum block end", n1, m1, sizeof(n1), 2, 4, offset, MAX_CRC_BLKS, NULL); - // - // Step #3 Multi point checksums - // - printf("\nStep #3: Reading Multipoint Checksum Block...\n"); - for(iTemp=0; iTemp<64; iTemp++) + if (found>0 && found<=MAX_CRC_BLKS) { - printf("%2d) ",iTemp+1); - fflush(stdout); - result = DoChecksumBlks(&ih, Config.multipoint_block_start+(Config.multipoint_block_len*iTemp)); - if (result == 1) { break; } // end of blocks; + for (i=0;i = %d bytes]\n", iTemp, iTemp*16); - if(ErrorsCorrected > 0) { - // write crc corrected file out - save_file(argv[2],ih.d.p,ih.len); + if (!found) + { + DEBUG_CRC("CRC/csum block end find failed\n"); + } + else if (found>MAX_CRC_BLKS) + { + DEBUG_CRC("Too many matches (%d). CRC/csum block end find failed\n", found); } -out: - - // close the file - if(ih.d.p != 0) { ifree_file(&ih); } - - // free config - if(osconfig != 0) { free_properties(osconfig); } - - printf("\nDone!\n%d/%d errors corrected!\n", ErrorsCorrected, ErrorsFound); + if (ret0||ret1) + { + if (ih->len==512*1024 || ih->pad == PADDING_TRY_512K_CRC) + { + printf("missing\n"); + printf(" Falling back to default 512k CRC blocks..."); + Config.crc[1].r.start=0x10000; + Config.crc[1].r.end=0x13fff; + Config.crc[2].r.start=0x14300; + Config.crc[2].r.end=0x17f67; + Config.crc[3].r.start=0x18191; + Config.crc[3].r.end=0x1fbff; + ret0=ret1=0; + } + } - return 0; + printf("%s\n", (ret0||ret1)?"FAIL":"OK"); + return ret0||ret1; } -/* - * GetRomInfo - * - * - uses config file to parse rom data and show interesting information about this rom dump - */ - -static int GetRomInfo(struct ImageHandle *ih, struct section *osconfig, uint32_t num_of) -{ - char str_data[1024]; - char type_str[256]; - char visible_str[256]; - char label_str[256]; - char offset_str[256]; - char length_str[256]; -#ifdef DEBUG - char * ptr_type; +#ifdef DEBUG_CRC_MATCHING +#define MAX_CRC_OFFSETS 10 +#else +#define MAX_CRC_OFFSETS MAX_CRC_BLKS #endif - char * ptr_visible; - char * ptr_label; - uint32_t ptr_offset; - uint32_t ptr_length; - int i; +static int FindMainCRCOffsets(const struct ImageHandle *ih) +{ + int i, found; + uint32_t offset[MAX_CRC_OFFSETS]; + // LL LL HH HH + uint8_t needle[] = {0xF6, 0xF5, 0x00, 0x00, 0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x80, 0x00, 0xDA, 0x00 /*, 0x00, 0x00, 0xe6, 0x00, 0x04, 0x02 */}; + uint8_t mask[] = {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff /*, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff */}; - if(ih == 0) return(-1); - // - // Dynamically walks through the config file and shows all properties defined... - // - for(i=1;i<=num_of;i++) - { - sprintf(type_str, "dump_%d_type", i); - sprintf(visible_str,"dump_%d_visible",i); - sprintf(label_str, "dump_%d_label", i); - sprintf(offset_str, "dump_%d_offset", i); - sprintf(length_str, "dump_%d_len", i); + printf(" Searching for main data CRC offsets..."); + DEBUG_FLUSH_CRC; - // get config out of ini file... -#ifdef DEBUG - ptr_type = get_property( osconfig, "dumps", type_str, NULL); -#endif - ptr_visible = get_property( osconfig, "dumps", visible_str, NULL); - ptr_label = get_property( osconfig, "dumps", label_str, NULL); - ptr_offset = get_property_value( osconfig, "dumps", offset_str, NULL); - ptr_length = get_property_value( osconfig, "dumps", length_str, NULL); + found=FindData(ih, "CRC offset", needle, mask, sizeof(needle), 3, 5, offset, MAX_CRC_OFFSETS, NULL); - if(ptr_length == 0) + if (found>0 && found<=MAX_CRC_OFFSETS) + { + for (i=0;i= ih->len) - { - printf("%s = INVALID OFFSET/LEN 0x%x/%d\n",ptr_label, ptr_offset, ptr_length); + } + + if (found!=3) + { + DEBUG_CRC("Did not find exactly 3 matches (got %d). CRC offset find failed\n", found); + for(i=1;i 1024) ptr_length = 1024; -#ifdef DEBUG - printf("\n%s = %s\n",type_str, ptr_type); - printf("%s = %s\n",visible_str, ptr_visible); - printf("%s = '%s'\n",label_str, ptr_label); - printf("%s = %p\n",offset_str, ptr_offset); - printf("%s = %p\n",length_str, ptr_length); -#endif - /* snprintf null terminates for us if string is too long :) */ - snprintf(str_data, ptr_length, "%s", ih->d.s+ptr_offset); - if(! strncmp("true",(char *)ptr_visible,4)) - { - printf("%-20.20s '%s'\n",ptr_label, str_data); - } - else - { - printf("%s = 'HIDDEN'\n",ptr_label); - } + printf("missing\n"); + return -1; + } + + /* if we found exactly 3 crc values, and region 4 exists, use region 3's crc for calcing 3+4 */ + if (Config.crc[4].r.start && Config.crc[4].r.end) + { + Config.crc[4].offset=Config.crc[3].offset; + Config.crc[3].offset=0; + } + + printf("OK\n"); + return 0; +} + +static int FindMainCSMOffsets(const struct ImageHandle *ih) +{ + int found; + uint32_t offset; + // LL LL HH HH + uint8_t needle0[] = {0xE1, 0x0C, 0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x80, 0x00, 0xDA, 0x00 /*, 0xf0, 0xe1, 0x0c, 0xe6 */}; + uint8_t needle1[] = {0x04, 0x00, 0xE6, 0xF4, 0x00, 0x00, 0xE6, 0xF5, 0x80, 0x00, 0xDA, 0x00 /*, 0xd8, 0x7e, 0xe6, 0x00 */}; + uint8_t mask[] = {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff /*, 0xf0, 0xff, 0xff, 0xff */}; + + printf(" Searching for main data checksum offsets..."); + DEBUG_FLUSH_CRC; + + found=FindData(ih, "Checksum offset", needle0, mask, sizeof(needle0), 2, 4, &offset, 1, NULL); + + if(found<1) { + /* try alternate pattern */ + found=FindData(ih, "Checksum offset", needle1, mask, sizeof(needle1), 2, 4, &offset, 1, NULL); + if (found!=1) { + printf("missing\n"); + return -1; } + } else if (found>1) { + DEBUG_CRC("Did not find exactly 1 match (got %d). Checksum offset find failed\n", found); + printf("missing\n"); + return -1; } + + DEBUG_CRC("Found checksum offset at 0x%x\n", offset); + Config.csm_offset=offset; + printf("OK\n"); return 0; } @@ -300,159 +2265,301 @@ static int DoMainCRCs(struct ImageHandle *ih) { int result=0; int i; + uint32_t nCalcCRCSeed = 0; - for (i=0; i<3; i++) + printf(" Main CRCs:\n"); + for (i=0; i<5; i++) { if(Config.crc[i].r.start && Config.crc[i].r.end) { - uint32_t nCalcCRC; uint32_t nStart = Config.crc[i].r.start; size_t nLen = Config.crc[i].r.end - Config.crc[i].r.start + 1; uint32_t nCRCAddr = Config.crc[i].offset; uint32_t nCRC; + uint32_t nCalcCRC; uint32_t *p32; - if (nStart>=Config.base_address) - { - nStart -= Config.base_address; - } + nCalcCRC = crc32(nCalcCRCSeed, ih->d.u8+nStart, nLen); - if (nCRCAddr>=Config.base_address) + printf(" %d) 0x%06X-0x%06X", i, Config.crc[i].r.start, Config.crc[i].r.end); + + if (nCRCAddr+4>ih->len) { - nCRCAddr -= Config.base_address; + printf(" @%05x INVALID ADDRESS\n", nCRCAddr); } - - nCalcCRC = crc32(0, ih->d.u8+nStart, nLen); - /* possibly unaligned, so we cant do tricks wtih ih->d.u32 */ - p32=(uint32_t *)(ih->d.u8 + nCRCAddr); - nCRC=le32toh(*p32); - printf("Adr: 0x%06X-0x%06X @0x%x CRC: 0x%08X CalcCRC: 0x%08X", - Config.crc[i].r.start, Config.crc[i].r.end, nCRCAddr, nCalcCRC, nCRC); - if (nCalcCRC != nCRC) + else if (nCRCAddr) { - ErrorsFound++; - if (Config.readonly) + struct ReportRecord *rr = CreateRecord("Main CRC", nCRCAddr, 3); + AddRangeStartLength(rr, nStart, nLen); + + /* possibly unaligned, so we cant do tricks wtih ih->d.u32 */ + p32=(uint32_t *)(ih->d.u8 + nCRCAddr); + nCRC=le32toh(*p32); + + printf(" @%05x CRC: %08X CalcCRC: %08X%s", nCRCAddr, nCRC, nCalcCRC, nCalcCRCSeed?"(r)":" "); + ChecksumsFound ++; + + if (nCalcCRC != nCRC) { - printf(" ** NOT OK **\n"); - result|=-1; + ErrorsFound++; + if (Config.readonly) + { + printf(" ** NOT OK **\n"); + result|=-1; + } + else + { + *p32=le32toh(nCalcCRC); + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } } else { - *p32=le32toh(nCalcCRC); - ErrorsCorrected++; - printf(" ** FIXED **\n"); + printf(" CRC OK\n"); } - } - else - { - printf(" CRC OK\n"); + } else { + printf(" CalcCRC: %08X%s\n", nCalcCRC, nCalcCRCSeed?"(r)":" "); } + if (Config.crc[0].r.start && Config.crc[0].r.end) + nCalcCRCSeed=nCalcCRC; + } + else + { + DEBUG_CRC(" %d) 0x%06X-0x%06X SKIPPED\n", i, + Config.crc[0].r.start, Config.crc[0].r.end); } } return result; } +static int DoMainCSMs(struct ImageHandle *ih) +{ + int result=0; + int i; + uint32_t nCalcCSM = 0; + uint32_t nCSMAddr = Config.csm_offset; + uint32_t *p32; + uint32_t nCSM, nCSMinv; + struct ReportRecord *rr; + if (nCSMAddr+4>ih->len) + { + printf(" @%05x INVALID ADDRESS\n", nCSMAddr); + return -1; + } -// -// Calculate the Bosch Motronic ME71 checksum for the given range -// -static uint32_t CalcChecksumBlk(struct ImageHandle *ih, const struct Range *r) -{ - uint32_t nStartAddr=r->start; - uint32_t nEndAddr=r->end; - uint32_t nChecksum = 0, nIndex; + /* possibly unaligned, so we cant do tricks wtih ih->d.u32 */ + p32 =(uint32_t *)(ih->d.u8 + nCSMAddr); + nCSM = le32toh(p32[0]); + nCSMinv = le32toh(p32[1]); - // We are only reading the ROM. Therefore the start address must be - // higher than ROMSTART. Ignore addresses lower than this and - // remove the offset for addresses we're interested in. - if (nStartAddr >= Config.base_address) //ROMSTART) + printf(" Main Checksums:\n"); + rr = CreateRecord("Main Checksums", nCSMAddr, 3); + + for (i=1; i<5; i++) + { + if(Config.crc[i].r.start && Config.crc[i].r.end) + { + AddRange(rr, &Config.crc[i].r); + printf(" %d) 0x%06X-0x%06X", i, + Config.crc[i].r.start, Config.crc[i].r.end); + + /* bytewise checksum */ + nCalcCSM += CalcChecksumBlk8(ih, &Config.crc[i].r); + + printf(" CalcCSM: %08X\n", nCalcCSM); + } + } + + printf(" @%05x CSM: %08X CalcCSM: %08X", nCSMAddr, nCSM, nCalcCSM); + ChecksumsFound ++; + + if (nCalcCSM != nCSM) { - nStartAddr -= Config.base_address; //ROMSTART; - nEndAddr -= Config.base_address; //ROMSTART; + ErrorsFound++; + if (Config.readonly) + { + printf(" ** NOT OK **\n"); + result|=-1; + } + else + { + p32[0]=le32toh(nCalcCSM); + p32[1]=le32toh(~nCalcCSM); + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } + } else if (nCSM != ~nCSMinv) { + printf(" @%05x CSM: %08X CSMinv: %08X (%08X)", nCSMAddr, nCSM, nCSMinv, ~nCSMinv); + + ErrorsFound++; + if (Config.readonly) + { + printf(" ** NOT OK **\n"); + result|=-1; + } + else + { + p32[1]=le32toh(~nCSM); + ErrorsCorrected++; + printf(" ** FIXED **\n"); + } } + else { - // The checksum block is outside our range - return 0xffffffffu; + printf(" OK\n"); + } + return result; +} + +static int FindMainProgramOffset(const struct ImageHandle *ih) +{ + int i, found=0, offset=0; + uint32_t needle[4]; + uint32_t mask[4]; + + printf(" Searching for main program checksum.."); + DEBUG_FLUSH_MAIN; + + needle[0]=htole32(Config.base_address); /* 0x000000 */ + needle[1]=htole32(Config.base_address+0x0fbff); /* 0x00fbff */ + needle[2]=htole32(Config.base_address+0x20000); /* 0x020000 */ + needle[3]=htole32(Config.base_address+0xf00ff); /* 0x07ffff 512k flash + 0x0febff oddball? + 0x0fffff 1M flash */ + mask[0]=htole32(0xffffffff); + mask[1]=htole32(0xffffffff); + mask[2]=htole32(0xffffffff); + mask[3]=htole32(0xfff700ff); + + for(i=0;i+sizeof(needle)len;i+=2) + { + i=search_image(ih, i, needle, mask, sizeof(needle), 2); + if (i<0) break; + DEBUG_MAIN("Found possible main block descriptor at 0x%x\n", i); + offset=i; + found++; } - if(nStartAddr>=ih->len || nEndAddr>=ih->len) + if (found==1) { - // The checksum block is outside our range - printf(" INVALID STARTADDDR/ENDADDR 0x%x/0x%x\n", nStartAddr, nEndAddr); - return 0xffffffffu; + DEBUG_MAIN("Found main block descriptor at 0x%x\n", offset); + Config.main_checksum_offset=offset; + printf("OK\n"); + return 0; + } + else if (found>1) + { + DEBUG_MAIN("Found %d main block descriptor matches\n", found); } - for(nIndex = nStartAddr/2; nIndex <= nEndAddr/2; nIndex++) + printf("FAIL\n"); + return -1; +} + +static int FindMainProgramFinal(const struct ImageHandle *ih) +{ + int offset=ih->len-0x20; + struct ChecksumPair *csum = (struct ChecksumPair *)(ih->d.u8+offset); + + if (csum->v == ~csum->iv) { - nChecksum+=le16toh(ih->d.u16[nIndex]); + DEBUG_MAIN("Found main csum at 0x%x\n", offset); + Config.main_checksum_final=offset; + return 0; } - return nChecksum; + + return -1; } // // Reads the main checksum for the whole ROM // -static int DoMainChecksum(struct ImageHandle *ih) +static int DoMainProgramCSM(struct ImageHandle *ih) { int errors=0; struct Range r[2]; struct ChecksumPair csum; + uint32_t nCsumAddr = Config.main_checksum_final; uint32_t nCalcChksum; uint32_t nCalcChksum2; + int inside=0; + + struct ReportRecord *rr = CreateRecord("Main Program Checksum", nCsumAddr, 8); - printf("ROM Checksum Block Offset Table 0x%X [16 bytes]\n\n", + printf(" ROM Checksum Block Offset Table @%05x [16 bytes]:\n", Config.main_checksum_offset); // C16x processors are little endian // copy from (le) buffer into our descriptor memcpy_from_le32(r, ih->d.u8+Config.main_checksum_offset, sizeof(r)); + if (NormalizeRange(ih, r) || NormalizeRange(ih, r+1) || + r[0].start==0xffffffff || r[1].start==0xffffffff) + { + printf(" ERROR! BAD MAIN CHECKSUM DESCRIPTOR(s)\n"); + ErrorsUncorrectable++; + return -1; + } + // block 1 - nCalcChksum = CalcChecksumBlk(ih, r); - printf("Adr: 0x%06X-0x%06X Block #1 - nCalcChksum=0x%04x\n", - r[0].start, r[0].end, nCalcChksum); + nCalcChksum = CalcChecksumBlk16(ih, &r[0]); + printf(" 1) 0x%06X-0x%06X CalcChk: %08X\n", r[0].start, r[0].end, nCalcChksum); if (r[0].end + 1 != r[1].start) { - uint32_t skip=r[0].end+1; - if (skip >= Config.base_address) - { - skip-=Config.base_address; - } - printf("Adr: 0x%06X-0x%06X MAP REGION SKIPPED, NOT PART OF MAIN CHECKSUM\n", - r[0].end+1, r[1].start-1); + struct Range sr; + uint32_t ss, sc; + AddRange(rr, &sr); + sr.start = r[0].end+1; + sr.end = r[1].start-1; + //struct Range sr = {.start = 0x10000, .end = 0x1FFFF}; + ss = CalcChecksumBlk16(ih, &sr); + sc = crc32(0, ih->d.u8+sr.start, sr.end-sr.start+1); + printf(" 0x%06X-0x%06X CalcChk: %08X CalcCRC: %08X SKIPPED\n", + sr.start, sr.end, ss, sc); } - // block 2 - nCalcChksum2= CalcChecksumBlk(ih, r+1); - printf("Adr: 0x%06X-0x%06X Block #2 - nCalcChksum=0x%04x\n", - r[1].start, r[1].end,nCalcChksum2); - - nCalcChksum += nCalcChksum2; - printf("\nRead in stored MAIN ROM checksum block @ 0x%X [8 bytes]\n", - Config.main_checksum_final); - // C16x processors are little endian // copy from (le) buffer - memcpy_from_le32(&csum, ih->d.u8+Config.main_checksum_final, sizeof(csum)); + memcpy_from_le32(&csum, ih->d.u8+nCsumAddr, sizeof(csum)); - printf("Chksum : 0x%08X", csum.v); - if(csum.v != ~csum.iv) - { - printf(" ~Chksum : 0x%08X INV NOT OK", csum.iv); - errors++; + // block 2 + /* test if checksum is inside block, if so, mark it */ + if (nCsumAddr+8 >= r[1].start && nCsumAddr <= r[1].end) inside++; + + AddRange(rr, &r[1]); + if (inside && csum.iv != ~csum.v) { + // if csum inside and iv!=~v, pre-correct iv so v+iv cancels out + // properly + uint32_t temp; + volatile struct ChecksumPair *cs= + (struct ChecksumPair *)(ih->d.u8+nCsumAddr); + temp = cs->iv; // save inv + cs->iv = ~cs->v; + nCalcChksum2 = CalcChecksumBlk16(ih, &r[1]); + cs->iv = temp; // restore inv + } else { + nCalcChksum2 = CalcChecksumBlk16(ih, &r[1]); } - printf(" CalcChk: 0x%08X", nCalcChksum); + nCalcChksum += nCalcChksum2; + + printf(" 2) 0x%06X-0x%06X CalcChk: %08X\n", r[1].start, r[1].end, + nCalcChksum); - if(csum.v != nCalcChksum) { errors++; } + printf(" @%05x Chk: %08X CalcChk: %08X", nCsumAddr, csum.v, nCalcChksum); + ChecksumsFound ++; + if (csum.v != nCalcChksum) { errors++; } + + if (csum.iv != ~csum.v) { errors++; } if(!errors) { - printf(" Main ROM checksum OK\n"); + printf(" OK%s\n", inside?" (i)":""); return 0; } @@ -461,91 +2568,256 @@ static int DoMainChecksum(struct ImageHandle *ih) if(Config.readonly) { printf(" ** NOT OK **\n"); + if (csum.iv!=~csum.v) { + printf(" %08X!=%08X, ChkInv: %08X ** NOT OK **\n", + csum.v, ~csum.iv, csum.iv); + if (inside) { + printf("*** WARNING! Checksum offset %x inside block 0x%x-0x%x!\n", + nCsumAddr, r[1].start, r[1].end); + } + } return -1; } csum.v = nCalcChksum; csum.iv = ~nCalcChksum; - memcpy_to_le32(ih->d.u8+Config.main_checksum_final, &csum, sizeof(csum)); + memcpy_to_le32(ih->d.u8+nCsumAddr, &csum, sizeof(csum)); - printf(" ** FIXED! **\n"); + printf(" ** FIXED **\n"); ErrorsCorrected+=errors; return 0; } +/* which=0: MP block #1 */ +/* which=1: MP block #2 */ +static int FindChecksumBlks(const struct ImageHandle *ih, int which) +{ + int i, found=0, offset=0; + uint32_t needle[2]; + int size=0; + + printf(" Searching for multipoint block descriptor #%d...", + which+1); + DEBUG_FLUSH_MULTIPOINT; + + if (which==0) { + needle[0]=htole32(Config.base_address+0x24000); + /* actually, mp #1 isn't allowed to match this, + its in mp #2 */ + needle[1]=htole32(Config.base_address+0x27fff); + size=4; + } else { +#ifdef CHECK_BOOTROM_MP + needle[0]=htole32(0); + needle[1]=htole32(0x3fff); +#else + needle[0]=htole32(Config.base_address); + needle[1]=htole32(Config.base_address+0x3fff); +#endif + size=8; + } + + for(i=0x10000;i+Config.multipoint_desc_lenlen;i+=2) + { + DEBUG_MULTIPOINT("%d: Searching starting at 0x%d\n", which+1, i); + i=search_image(ih, i, needle, NULL, size, 2); + if (i<0) break; + else { + struct MultipointDescriptor *desc = + (struct MultipointDescriptor *)(ih->d.u8+i); + + /* for mp block 1, don't be picky about inv */ + if ((which==0) || desc->csum.v==~desc->csum.iv) + { + /* make sure we don't match the mp #2 when looking for #1 */ + if(which || desc->r.end != needle[1]) { + DEBUG_MULTIPOINT("%d: Found possible multipoint descriptor #%d at 0x%x\n", + which+1, found+1, i); + DEBUG_MULTIPOINT("0x%x-0x%x\n", desc->r.start, desc->r.end); + offset=i; + found++; + } + } + } + } + + if (found==1) + { + /* test next block to make sure it looks reasonable */ + struct MultipointDescriptor *desc = + (struct MultipointDescriptor *)(ih->d.u8+offset+Config.multipoint_desc_len); + + /* for mp block 1, don't be picky about inv */ + if ((which==0) || desc->csum.v==~desc->csum.iv) + { + DEBUG_MULTIPOINT("Found descriptor #%d at 0x%x\n", which+1, + offset); + Config.multipoint_block_start[which]=offset; + printf("OK\n"); + return 0; + } + } + + printf(which==0?"missing\n":"FAIL\n"); + return -1; +} + +static int MP_callback(void *data, struct ReportRecord *rr) +{ + struct ChecksumPair *pcsum, csum; + struct ImageHandle *ih = data; + uint32_t nCalcChksum = 0; + struct RangeList *rl; + struct Range full={0xffffffff,0}; + + /* assume we already corrected v vs iv */ + list_for_each_entry(rl, &rr->data.list, list) { + if (rl->r.startr.start; + if (rl->r.end>full.end) full.end=rl->r.end; + nCalcChksum += CalcChecksumBlk16(ih, &rl->r); + } + + pcsum=(struct ChecksumPair *)(ih->d.u8+rr->checksum.start); + memcpy_from_le32(&csum, pcsum, sizeof(csum)); + printf(" <%x> 0x%06X-0x%06X Chk: %08X CalcChk: %08X", + rr->checksum.start-8, full.start, full.end, csum.v, nCalcChksum); + if (csum.v != nCalcChksum) { + ErrorsFound++; + csum.v = nCalcChksum; + csum.iv = ~nCalcChksum; + if (Config.readonly) { + printf(" ** NOT OK ** (recheck)\n"); + } else { + memcpy_to_le32(pcsum, &csum, sizeof(csum)); + ErrorsCorrected++; + printf(" ** FIXED ** (recheck)\n"); + } + } else { + printf(" OK (recheck)\n"); + } + + return 0; +} + // Reads the individual checksum blocks that start at nStartBlk -static int DoChecksumBlks(struct ImageHandle *ih, uint32_t nStartBlk) +// -2 for ignored bootrom block +// -1 for error +// 0 for no error +// 1 for last block +static int DoChecksumBlk(struct ImageHandle *ih, uint32_t nStartBlk, struct strbuf *buf, int bootrom) { // read the ROM byte by byte to make this code endian independant // C16x processors are little endian struct MultipointDescriptor desc; - uint32_t nCalcChksum; + struct MultipointDescriptor *pDesc; + uint32_t nCsumAddr, nCalcChksum; int errors=0; + int inside=0; - printf("<%x> ",nStartBlk); - fflush(stdout); + sbprintf(buf, "<%05x> ", nStartBlk); if(nStartBlk + sizeof(desc) >= ih->len) { - printf(" INVALID STARTBLK/LEN 0x%x/%ld ** NOT OK **\n", nStartBlk, (long int)ih->len); + sbprintf(buf, " ERROR! INVALID STARTBLK/LEN 0x%x/%ld ** NOT OK **\n", nStartBlk, (long int)ih->len); + ErrorsUncorrectable++; return -1; // Uncorrectable Error } + nCsumAddr = nStartBlk + offsetof(struct MultipointDescriptor, csum.v); + // C16x processors are little endian // copy from (le) buffer into our descriptor memcpy_from_le32(&desc, ih->d.u8+nStartBlk, sizeof(desc)); + if (!bootrom) { + if (NormalizeRange(ih, &desc.r)) + { + ErrorsUncorrectable++; + return -1; + } + } + + /* + if (Verbose>2) { + sbprintf(buf, "\n"); + sbprintdesc(buf, &desc); + } + */ - printf("Adr: 0x%04X-0x%04X ", desc.r.start, desc.r.end); - fflush(stdout); + sbprintf(buf, " 0x%06X-0x%06X ", desc.r.start, desc.r.end); if(desc.r.start==0xffffffff) { - printf(" END\n"); + sbprintf(buf, " END\n"); return 1; // end of blks } - if(desc.r.start>=desc.r.end) - { - printf(" ** NOT OK **\n"); - return -1; // Uncorrectable Error - } + sbprintf(buf, "Chk: %08X", desc.csum.v); + + /* test if checksum is inside block, if so, mark it */ + if (nCsumAddr+8 >= desc.r.start && nCsumAddr <= desc.r.end) inside++; + + if (bootrom && ih->bootrom_whitelist) { + /* whitelisted */ + nCalcChksum = desc.csum.v; + sbprintf(buf, " Boot: (whitelisted)"); + } else { + struct ReportRecord *rr = CreateRecord("MP Block", nCsumAddr, sizeof(desc.csum)); + rr->callback = MP_callback; + rr->cb_data = ih; + AddRange(rr, &desc.r); + if (inside && desc.csum.iv != ~desc.csum.v) { + // if csum inside and iv!=~v, pre-correct iv so v+iv cancels out + // properly + uint32_t temp; + volatile struct ChecksumPair *cs= + (struct ChecksumPair *)(ih->d.u8+nCsumAddr); + temp = cs->iv; // save inv + cs->iv = ~cs->v; + nCalcChksum = CalcChecksumBlk16(ih, &desc.r); + cs->iv = temp; // restore inv + } else { + nCalcChksum = CalcChecksumBlk16(ih, &desc.r); + } - printf("Chk: 0x%08X", desc.csum.v); + sbprintf(buf, " CalcChk: %08X", nCalcChksum); + ChecksumsFound ++; - if(desc.csum.v != ~desc.csum.iv) - { - printf(" ~0x%08X INV NOT OK", desc.csum.iv); - errors++; + if (desc.csum.v != nCalcChksum) { errors++; } } - // calc checksum - nCalcChksum = CalcChecksumBlk(ih, &desc.r); - - printf(" CalcChk: 0x%08X", nCalcChksum); - if(desc.csum.v != nCalcChksum) { errors++; } + if (desc.csum.iv != ~desc.csum.v) { errors++; } if (!errors) { - printf(" OK\n"); - return 0; + sbprintf(buf, " OK%s\n", inside?" (i)":""); + return bootrom?-2:0; } ErrorsFound+=errors; if (Config.readonly) { - printf(" ** NOT OK **\n"); + sbprintf(buf, " ** NOT OK **\n"); + if (desc.csum.iv != ~desc.csum.v) { + sbprintf(buf, "%26s%08X!=%08X, ChkInv: %08X ** NOT OK **\n", + "", desc.csum.v, ~desc.csum.iv, desc.csum.iv); + if (inside) { + sbprintf(buf, "*** WARNING! Checksum offset %x inside block 0x%x-0x%x!\n", + nCsumAddr, desc. r.start, desc.r.end); + } + } return -1; } desc.csum.v = nCalcChksum; desc.csum.iv = ~nCalcChksum; - memcpy_to_le32(ih->d.u8+nStartBlk, &desc, sizeof(desc)); + pDesc=(struct MultipointDescriptor *)(ih->d.u8+nStartBlk); + memcpy_to_le32(&pDesc->csum, &desc.csum, sizeof(desc.csum)); - printf(" ** FIXED! **\n"); + sbprintf(buf, " ** FIXED **\n"); ErrorsCorrected+=errors; return 0; } -// vim:ts=4:sw=4 +// vim:ts=4:sw=4:noexpandtab diff --git a/mpir/gmp.h b/mpir/gmp.h new file mode 100644 index 0000000..a4ac54d --- /dev/null +++ b/mpir/gmp.h @@ -0,0 +1,1944 @@ +/* generated from gmp-h.in by gen_mpir_h.bat */ +/* Definitions for GNU multiple precision functions. -*- mode: c -*- +Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, +2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, +Inc. +Copyright 2008 William Hart, Gonzalo Tornaria +This file is part of the MPIR Library. +The MPIR Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. +The MPIR Library 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 Lesser General Public +License for more details. +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ +#ifndef __GMP_H__ +#ifdef __SUNPRO_CC /* See: http://trac.sagemath.org/sage_trac/ticket/7849 */ +#include /* This is Bill Hart's fix, but I've applied it only */ +#include /* on Sun Studio */ +#endif +#if defined (__cplusplus) +#include /* for size_t */ +#include /* for std::istream, std::ostream, std::string */ +#include +#endif +/* Instantiated by configure. */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +#ifdef _WIN32 +# ifdef _WIN64 +# define _LONG_LONG_LIMB 1 +# define GMP_LIMB_BITS 64 +# else +# define GMP_LIMB_BITS 32 +# endif +# define __GMP_BITS_PER_MP_LIMB GMP_LIMB_BITS +# define SIZEOF_MP_LIMB_T (GMP_LIMB_BITS >> 3) +# define GMP_NAIL_BITS 0 +#endif +#endif +#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) +#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS) +#define GMP_NUMB_MAX GMP_NUMB_MASK +#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) +#ifndef __GNU_MP__ +#define __GNU_MP__ 4 +#define __need_size_t /* tell gcc stddef.h we only want size_t */ +#if ! defined (__cplusplus) +#include /* for size_t */ +#endif +#undef __need_size_t +/* Instantiated by configure. */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +#endif +/* #if defined(__GMP_WITHIN_CONFIGURE) && defined(_WIN64) */ +#ifdef __WIN64 +#define _LONG_LONG_LIMB 1 +#endif +/* __STDC__ - some ANSI compilers define this only to 0, hence the use of + "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 + sets __STDC__ to 0, but requires "##" for token pasting. + _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but + don't always define __STDC__. + __DECC - current versions of DEC C (5.9 for instance) for alpha are ANSI, + but don't define __STDC__ in their default mode. Don't know if old + versions might have been K&R, but let's not worry about that unless + someone is still using one. + _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 + mode, but doesn't define __STDC__. + _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za + option is given (in which case it's 1). + _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that + all w32 compilers are ansi. + Note: This same set of tests is used by gen-psqr.c and + demos/expr/expr-impl.h, so if anything needs adding, then be sure to + update those too. */ +#if defined (__STDC__) \ + || defined (__cplusplus) \ + || defined (_AIX) \ + || defined (__DECC) \ + || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ + || defined (_MSC_VER) \ + || defined (_WIN32) +#define __GMP_HAVE_CONST 1 +#define __GMP_HAVE_PROTOTYPES 1 +#define __GMP_HAVE_TOKEN_PASTE 1 +#else +#define __GMP_HAVE_CONST 0 +#define __GMP_HAVE_PROTOTYPES 0 +#define __GMP_HAVE_TOKEN_PASTE 0 +#endif +#if __GMP_HAVE_CONST +#define __gmp_const const +#define __gmp_signed signed +#else +#define __gmp_const +#define __gmp_signed +#endif +/* __GMP_DECLSPEC supports Windows DLL versions of libmpir, and is empty in + all other circumstances. + When compiling objects for libmpir, __GMP_DECLSPEC is an export directive, + or when compiling for an application it's an import directive. The two + cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles + (and not defined from an application). + __GMP_DECLSPEC_XX is similarly used for libmpirxx. __GMP_WITHIN_GMPXX + indicates when building libmpirxx, and in that case libmpirxx functions are + exports, but libmpir functions which might get called are imports. + libmp.la uses __GMP_DECLSPEC, just as if it were libmpir.la. libmpir and + libmp don't call each other, so there's no conflict or confusion. + Libtool DLL_EXPORT define is not used. + There's no attempt to support GMP built both static and DLL. Doing so + would mean applications would have to tell us which of the two is going + to be used when linking, and that seems very tedious and error prone if + using GMP by hand, and equally tedious from a package since autoconf and + automake don't give much help. + __GMP_DECLSPEC is required on all documented global functions and + variables, the various internals in gmp-impl.h etc can be left unadorned. + But internals used by the test programs or speed measuring programs + should have __GMP_DECLSPEC, and certainly constants or variables must + have it or the wrong address will be resolved. + In gcc __declspec can go at either the start or end of a prototype. + In Microsoft C __declspec must go at the start, or after the type like + void __declspec(...) *foo()". There's no __dllexport or anything to + guard against someone foolish #defining dllexport. _export used to be + available, but no longer. + In Borland C _export still exists, but needs to go after the type, like + "void _export foo();". Would have to change the __GMP_DECLSPEC syntax to + make use of that. Probably more trouble than it's worth. */ +#if defined (__GNUC__) +#define __GMP_DECLSPEC_EXPORT __declspec(__dllexport__) +#define __GMP_DECLSPEC_IMPORT __declspec(__dllimport__) +#endif +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) +#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) +#endif +#ifdef __WATCOMC__ +#define __GMP_DECLSPEC_EXPORT __export +#define __GMP_DECLSPEC_IMPORT __import +#endif +#ifdef __IBMC__ +#define __GMP_DECLSPEC_EXPORT _Export +#define __GMP_DECLSPEC_IMPORT _Import +#endif +#if defined( _MSC_VER ) +# if defined( MSC_BUILD_DLL ) +# define __GMP_LIBGMP_DLL 1 +# define __GMP_WITHIN_GMP 1 +# define __GMP_WITHIN_GMPXX 1 +# elif defined( MSC_USE_DLL ) +# define __GMP_LIBGMP_DLL 1 +# endif +#endif +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMP +/* compiling to go into a DLL libmpir */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into an application which will link to a DLL libmpir */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC +#endif +#ifdef __GMP_SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif +#ifdef _WIN64 +#define BITS_PER_UI BITS_PER_MP_LIMB +typedef mp_limb_t mpir_ui; +typedef mp_limb_signed_t mpir_si; +typedef mpir_ui mp_bitcnt_t; +#else +#define BITS_PER_UI BITS_PER_ULONG +typedef unsigned long mpir_ui; +typedef long mpir_si; +typedef mpir_ui mp_bitcnt_t; +#endif +#define GMP_UI_MAX ((mpir_ui)(~(mpir_ui)0)) +#define GMP_UI_HIBIT (GMP_UI_MAX ^ (GMP_UI_MAX >> 1)) +#define GMP_SI_MAX ((mpir_si)(GMP_UI_MAX ^ GMP_UI_HIBIT)) +#define GMP_SI_MIN ((mpir_si)GMP_UI_HIBIT) +#define __GMP_BITCNT_MAX (~(mp_bitcnt_t)0) +/* For reference, note that the name __mpz_struct gets into C++ mangled + function names, which means although the "__" suggests an internal, we + must leave this name for binary compatibility. */ +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#endif /* __GNU_MP__ */ +typedef __mpz_struct mpz_t[1]; +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +#if defined( _WIN64) +#define __GMP_MP_SIZE_T_INT 0 +typedef long long int mp_size_t; +typedef long int mp_exp_t; +#else +#define __GMP_MP_SIZE_T_INT 0 +typedef long int mp_size_t; +typedef long int mp_exp_t; +#endif +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +} __mpq_struct; +typedef __mpq_struct mpq_t[1]; +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to by the + _mp_d field contains `prec' + 1 limbs. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; +typedef __mpf_struct mpf_t[1]; +/* Available random number generation algorithms. */ +typedef enum +{ + GMP_RAND_ALG_DEFAULT = 0, + GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ +} gmp_randalg_t; +/* Random state struct. */ +typedef struct +{ + mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ + gmp_randalg_t _mp_alg; /* Currently unused. */ + union { + void *_mp_lc; /* Pointer to function pointers structure. */ + } _mp_algdata; +} __gmp_randstate_struct; +typedef __gmp_randstate_struct gmp_randstate_t[1]; +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMPXX +/* compiling to go into a DLL libmpirxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into a application which will link to a DLL libmpirxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC_XX +#endif +#if __GMP_HAVE_PROTOTYPES +#define __GMP_PROTO(x) x +#else +#define __GMP_PROTO(x) () +#endif +#ifndef __MPN +#if __GMP_HAVE_TOKEN_PASTE +#define __MPN(x) __gmpn_##x +#else +#define __MPN(x) __gmpn_/**/x +#endif +#endif +/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, + defines EOF but not FILE. */ +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ \ + || defined (_MSL_STDIO_H) /* Metrowerks */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ +#define _GMP_H_HAVE_FILE 1 +#endif +/* In ISO C, if a prototype involving "struct obstack *" is given without + that structure defined, then the struct is scoped down to just the + prototype, causing a conflict if it's subsequently defined for real. So + only give prototypes if we've got obstack.h. */ +#if defined (_OBSTACK_H) /* glibc */ +#define _GMP_H_HAVE_OBSTACK 1 +#endif +/* The prototypes for gmp_vprintf etc are provided only if va_list is + available, via an application having included or . + Usually va_list is a typedef so can't be tested directly, but C99 + specifies that va_start is a macro (and it was normally a macro on past + systems too), so look for that. + will define some sort of va_list for vprintf and vfprintf, but + let's not bother trying to use that since it's not standard and since + application uses for gmp_vprintf etc will almost certainly require the + whole or anyway. */ +#ifdef va_start +#define _GMP_H_HAVE_VA_LIST 1 +#endif +/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ +#if defined (__GNUC__) && defined (__GNUC_MINOR__) +#define __GMP_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GMP_GNUC_PREREQ(maj, min) 0 +#endif +/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically + it means a function does nothing but examine its arguments and memory + (global or via arguments) to generate a return value, but changes nothing + and has no side-effects. __GMP_NO_ATTRIBUTE_CONST_PURE lets + tune/common.c etc turn this off when trying to write timing loops. */ +#if __GMP_GNUC_PREREQ (2,96) && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) +#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +#define __GMP_ATTRIBUTE_PURE +#endif +/* __GMP_CAST allows us to use static_cast in C++, so our macros are clean + to "g++ -Wold-style-cast". + Casts in "extern inline" code within an extern "C" block don't induce + these warnings, so __GMP_CAST only needs to be used on documented + macros. */ +#ifdef __cplusplus +#define __GMP_CAST(type, expr) (static_cast (expr)) +#else +#define __GMP_CAST(type, expr) ((type) (expr)) +#endif +/* An empty "throw ()" means the function doesn't throw any C++ exceptions, + this can save some stack frame info in applications. + Currently it's given only on functions which never divide-by-zero etc, + don't allocate memory, and are expected to never need to allocate memory. + This leaves open the possibility of a C++ throw from a future GMP + exceptions scheme. + mpz_set_ui etc are omitted to leave open the lazy allocation scheme + described in doc/tasks.html. mpz_get_d etc are omitted to leave open + exceptions for float overflows. + Note that __GMP_NOTHROW must be given on any inlines the same as on their + prototypes (for g++ at least, where they're used together). Note also + that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like + __GMP_ATTRIBUTE_PURE. */ +#if defined (__cplusplus) +#define __GMP_NOTHROW throw () +#else +#define __GMP_NOTHROW +#endif +/* PORTME: What other compilers have a useful "extern inline"? "static + inline" would be an acceptable substitute if the compiler (or linker) + discards unused statics. */ +/* gcc has __inline__ in all modes, including strict ansi. Give a prototype + for an inline too, so as to correctly specify "dllimport" on windows, in + case the function is called rather than inlined. */ +#ifdef __GNUC__ +#if defined(__APPLE_CC__) && (__APPLE_CC__ != 1) /* FSF GCC sets this flag to 1 on Apple machines */ +#if ! (__APPLE_CC__ >= 5465 && __STDC_VERSION__ >= 199901L) +#define __GMP_EXTERN_INLINE extern __inline__ +#define __GMP_INLINE_PROTOTYPES 1 +#endif +#else /*GNU CC*/ +#if defined(__GNUC_STDC_INLINE__) || defined (__GNUC_GNU_INLINE__) +#define __GMP_EXTERN_INLINE extern __inline__ __attribute__((__gnu_inline__)) +#else +#define __GMP_EXTERN_INLINE extern __inline__ +#endif +#define __GMP_INLINE_PROTOTYPES 1 +#endif +#endif +/* DEC C (eg. version 5.9) supports "static __inline foo()", even in -std1 + strict ANSI mode. Inlining is done even when not optimizing (ie. -O0 + mode, which is the default), but an unnecessary local copy of foo is + emitted unless -O is used. "extern __inline" is accepted, but the + "extern" appears to be ignored, ie. it becomes a plain global function + but which is inlined within its file. Don't know if all old versions of + DEC C supported __inline, but as a start let's do the right thing for + current versions. */ +#ifdef __DECC +#define __GMP_EXTERN_INLINE static __inline +#endif +/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict + ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes + place under -O. Without -O "foo" seems to be emitted whether it's used + or not, which is wasteful. "extern inline foo()" isn't useful, the + "extern" is apparently ignored, so foo is inlined if possible but also + emitted as a global, which causes multiple definition errors when + building a shared libmpir. */ +#ifdef __SCO_VERSION__ +#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE static inline +#endif +#endif +#if defined _MSC_VER +#define __GMP_EXTERN_INLINE static __inline +#endif +/* C++ always has "inline" and since it's a normal feature the linker should + discard duplicate non-inlined copies, or if it doesn't then that's a + problem for everyone, not just GMP. */ +#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE inline +#endif +/* Don't do any inlining within a configure run, since if the compiler ends + up emitting copies of the code into the object file it can end up + demanding the various support routines (like mpn_popcount) for linking, + making the "alloca" test and perhaps others fail. And on hppa ia64 a + pre-release gcc 3.2 was seen not respecting the "extern" in "extern + __inline__", triggering this problem too. */ +#if defined (__GMP_WITHIN_CONFIGURE) && ! __GMP_WITHIN_CONFIGURE_INLINE +#undef __GMP_EXTERN_INLINE +#endif +/* By default, don't give a prototype when there's going to be an inline + version. Note in particular that Cray C++ objects to the combination of + prototype and inline. */ +#ifdef __GMP_EXTERN_INLINE +#ifndef __GMP_INLINE_PROTOTYPES +#define __GMP_INLINE_PROTOTYPES 0 +#endif +#else +#define __GMP_INLINE_PROTOTYPES 1 +#endif +#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) +/* __GMP_USHRT_MAX is not "~ (unsigned short) 0" because short is promoted + to int by "~". */ +#define __GMP_UINT_MAX (~ (unsigned) 0) +#define __GMP_ULONG_MAX (~ (unsigned long) 0) +#define __GMP_USHRT_MAX ((unsigned short) ~0) +/* __builtin_expect is in gcc 3.0, and not in 2.95. */ +#if __GMP_GNUC_PREREQ (3,0) +#define __GMP_LIKELY(cond) __builtin_expect ((cond) != 0, 1) +#define __GMP_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) +#else +#define __GMP_LIKELY(cond) (cond) +#define __GMP_UNLIKELY(cond) (cond) +#endif +/* Allow direct user access to numerator and denominator of a mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) +#if defined (__cplusplus) +extern "C" { +using std::FILE; +#endif +#define mp_set_memory_functions __gmp_set_memory_functions +__GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))) __GMP_NOTHROW; +#define mp_get_memory_functions __gmp_get_memory_functions +__GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t))) __GMP_NOTHROW; +#define mp_bits_per_limb __gmp_bits_per_limb +__GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; +#define gmp_errno __gmp_errno +__GMP_DECLSPEC extern int gmp_errno; +#define gmp_version __gmp_version +__GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; +#define mpir_version __mpir_version +__GMP_DECLSPEC extern __gmp_const char * __gmp_const mpir_version; +/**************** Random number routines. ****************/ +#define gmp_randinit_default __gmp_randinit_default +__GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); +#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp +__GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, + mpz_srcptr, mpir_ui, + mp_bitcnt_t)); +#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size +__GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, mp_bitcnt_t)); +#define gmp_randinit_mt __gmp_randinit_mt +__GMP_DECLSPEC void gmp_randinit_mt __GMP_PROTO ((gmp_randstate_t)); +#define gmp_randinit_set __gmp_randinit_set +__GMP_DECLSPEC void gmp_randinit_set __GMP_PROTO ((gmp_randstate_t, __gmp_const __gmp_randstate_struct *)); +#define gmp_randseed __gmp_randseed +__GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); +#define gmp_randseed_ui __gmp_randseed_ui +__GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, mpir_ui)); +#define gmp_randclear __gmp_randclear +__GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); +#define gmp_urandomb_ui __gmp_urandomb_ui +__GMP_DECLSPEC mpir_ui gmp_urandomb_ui __GMP_PROTO ((gmp_randstate_t, mpir_ui)); +#define gmp_urandomm_ui __gmp_urandomm_ui +__GMP_DECLSPEC mpir_ui gmp_urandomm_ui __GMP_PROTO ((gmp_randstate_t, mpir_ui)); +/**************** Formatted output routines. ****************/ +#define gmp_asprintf __gmp_asprintf +__GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, __gmp_const char *, ...)); +#define gmp_fprintf __gmp_fprintf +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +#endif +#define gmp_obstack_printf __gmp_obstack_printf +#if defined (_GMP_H_HAVE_OBSTACK) +__GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, __gmp_const char *, ...)); +#endif +#define gmp_obstack_vprintf __gmp_obstack_vprintf +#if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, __gmp_const char *, va_list)); +#endif +#define gmp_printf __gmp_printf +__GMP_DECLSPEC int gmp_printf __GMP_PROTO ((__gmp_const char *, ...)); +#define gmp_snprintf __gmp_snprintf +__GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, ...)); +#define gmp_sprintf __gmp_sprintf +__GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, __gmp_const char *, ...)); +#define gmp_vasprintf __gmp_vasprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, __gmp_const char *, va_list)); +#endif +#define gmp_vfprintf __gmp_vfprintf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +#endif +#define gmp_vprintf __gmp_vprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((__gmp_const char *, va_list)); +#endif +#define gmp_vsnprintf __gmp_vsnprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, va_list)); +#endif +#define gmp_vsprintf __gmp_vsprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_list)); +#endif +/**************** Formatted input routines. ****************/ +#define gmp_fscanf __gmp_fscanf +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +#endif +#define gmp_scanf __gmp_scanf +__GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((__gmp_const char *, ...)); +#define gmp_sscanf __gmp_sscanf +__GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, ...)); +#define gmp_vfscanf __gmp_vfscanf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +#endif +#define gmp_vscanf __gmp_vscanf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((__gmp_const char *, va_list)); +#endif +#define gmp_vsscanf __gmp_vsscanf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, va_list)); +#endif +/**************** Integer (i.e. Z) routines. ****************/ +#define _mpz_realloc __gmpz_realloc +#define mpz_realloc __gmpz_realloc +__GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); +#define mpz_abs __gmpz_abs +#define __GMP_MPZ_ABS_MIN_ALLOC(x,y) (__GMP_ABS(y->_mp_size)) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) +__GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif +#define __GMP_MPZ_ADD_MIN_ALLOC(x,y,z) (__GMP_MAX(__GMP_ABS(y->_mp_size),__GMP_ABS(z->_mp_size))+1) +#define mpz_add __gmpz_add +__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define __GMP_MPZ_ADD_UI_MIN_ALLOC(x,y,z) (__GMP_MAX(__GMP_ABS(y->_mp_size),1+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS)+1) +#define mpz_add_ui __gmpz_add_ui +__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_addmul __gmpz_addmul +__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_addmul_ui __gmpz_addmul_ui +__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_and __gmpz_and +__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_array_init __gmpz_array_init +__GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); +#define mpz_bin_ui __gmpz_bin_ui +__GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_bin_uiui __gmpz_bin_uiui +__GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, mpir_ui, mpir_ui)); +#define mpz_cdiv_q __gmpz_cdiv_q +__GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp +__GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui +__GMP_DECLSPEC mpir_ui mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_cdiv_qr __gmpz_cdiv_qr +__GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui +__GMP_DECLSPEC mpir_ui mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_cdiv_r __gmpz_cdiv_r +__GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp +__GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui +__GMP_DECLSPEC mpir_ui mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_cdiv_ui __gmpz_cdiv_ui +__GMP_DECLSPEC mpir_ui mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpz_clear __gmpz_clear +__GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); +#define mpz_clears __gmpz_clears +__GMP_DECLSPEC void mpz_clears __GMP_PROTO ((mpz_ptr, ...)); +#define mpz_clrbit __gmpz_clrbit +__GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, mp_bitcnt_t)); +#define mpz_cmp __gmpz_cmp +__GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_cmp_d __gmpz_cmp_d +__GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; +#define _mpz_cmp_si __gmpz_cmp_si +__GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, mpir_si)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define _mpz_cmp_ui __gmpz_cmp_ui +__GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_cmpabs __gmpz_cmpabs +__GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_cmpabs_d __gmpz_cmpabs_d +__GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; +#define mpz_cmpabs_ui __gmpz_cmpabs_ui +__GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_com __gmpz_com +__GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#define mpz_combit __gmpz_combit +__GMP_DECLSPEC void mpz_combit __GMP_PROTO ((mpz_ptr, mp_bitcnt_t)); +#define mpz_congruent_p __gmpz_congruent_p +__GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p +__GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mp_bitcnt_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_congruent_ui_p __gmpz_congruent_ui_p +__GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, mpir_ui, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpz_divexact __gmpz_divexact +__GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_divexact_ui __gmpz_divexact_ui +__GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_divisible_p __gmpz_divisible_p +__GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_divisible_ui_p __gmpz_divisible_ui_p +__GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p +__GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, mp_bitcnt_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_dump __gmpz_dump +__GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); +#define mpz_export __gmpz_export +__GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr)); +#define mpz_fac_ui __gmpz_fac_ui +__GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_2fac_ui __gmpz_2fac_ui +__GMP_DECLSPEC void mpz_2fac_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_mfac_uiui __gmpz_mfac_uiui +__GMP_DECLSPEC void mpz_mfac_uiui __GMP_PROTO ((mpz_ptr, mpir_ui, mpir_ui)); +#define mpz_primorial_ui __gmpz_primorial_ui +__GMP_DECLSPEC void mpz_primorial_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_fdiv_q __gmpz_fdiv_q +__GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp +__GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui +__GMP_DECLSPEC mpir_ui mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_fdiv_qr __gmpz_fdiv_qr +__GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui +__GMP_DECLSPEC mpir_ui mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_fdiv_r __gmpz_fdiv_r +__GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp +__GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui +__GMP_DECLSPEC mpir_ui mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_fdiv_ui __gmpz_fdiv_ui +__GMP_DECLSPEC mpir_ui mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpz_fib_ui __gmpz_fib_ui +__GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_fib2_ui __gmpz_fib2_ui +__GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpir_ui)); +#define mpz_fits_sint_p __gmpz_fits_sint_p +__GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_fits_si_p __gmpz_fits_si_p +__GMP_DECLSPEC int mpz_fits_si_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_fits_slong_p __gmpz_fits_slong_p +__GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_fits_sshort_p __gmpz_fits_sshort_p +__GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_fits_uint_p __gmpz_fits_uint_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) +__GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_fits_ui_p __gmpz_fits_ui_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ui_p) +__GMP_DECLSPEC int mpz_fits_ui_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_fits_ulong_p __gmpz_fits_ulong_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) +__GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_fits_ushort_p __gmpz_fits_ushort_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) +__GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_gcd __gmpz_gcd +__GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_gcd_ui __gmpz_gcd_ui +__GMP_DECLSPEC mpir_ui mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_gcdext __gmpz_gcdext +__GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_get_d __gmpz_get_d +__GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_get_d_2exp __gmpz_get_d_2exp +__GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long *, mpz_srcptr)); +#define mpz_get_si __gmpz_get_si +__GMP_DECLSPEC /* signed */ mpir_si mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_get_str __gmpz_get_str +__GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); +#define mpz_get_ui __gmpz_get_ui +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) +__GMP_DECLSPEC mpir_ui mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_getlimbn __gmpz_getlimbn +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) +__GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_hamdist __gmpz_hamdist +__GMP_DECLSPEC mp_bitcnt_t mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_import __gmpz_import +__GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, __gmp_const void *)); +#define mpz_init __gmpz_init +__GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); +#define mpz_init2 __gmpz_init2 +__GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, mp_bitcnt_t)); +#define mpz_inits __gmpz_inits +__GMP_DECLSPEC void mpz_inits __GMP_PROTO ((mpz_ptr, ...)); +#define mpz_init_set __gmpz_init_set +__GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#define mpz_init_set_d __gmpz_init_set_d +__GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); +#define mpz_init_set_si __gmpz_init_set_si +__GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, mpir_si)); +#define mpz_init_set_str __gmpz_init_set_str +__GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); +#define mpz_init_set_ui __gmpz_init_set_ui +__GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_inp_raw __gmpz_inp_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); +#endif +#define mpz_inp_str __gmpz_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); +#endif +#define mpz_invert __gmpz_invert +__GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_ior __gmpz_ior +__GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_jacobi __gmpz_jacobi +__GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_kronecker mpz_jacobi /* alias */ +#define mpz_kronecker_si __gmpz_kronecker_si +__GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, mpir_si)) __GMP_ATTRIBUTE_PURE; +#define mpz_kronecker_ui __gmpz_kronecker_ui +__GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpz_si_kronecker __gmpz_si_kronecker +__GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((mpir_si, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_ui_kronecker __gmpz_ui_kronecker +__GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((mpir_ui, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_lcm __gmpz_lcm +__GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_lcm_ui __gmpz_lcm_ui +__GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_legendre mpz_jacobi /* alias */ +#define mpz_lucnum_ui __gmpz_lucnum_ui +__GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_lucnum2_ui __gmpz_lucnum2_ui +__GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpir_ui)); +#define mpz_millerrabin __gmpz_millerrabin +__GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; +#define mpz_miller_rabin __gmpz_miller_rabin +__GMP_DECLSPEC int mpz_miller_rabin __GMP_PROTO ((mpz_srcptr, int, gmp_randstate_t)) __GMP_ATTRIBUTE_PURE; +#define mpz_mod __gmpz_mod +__GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ +#define __GMP_MPZ_MUL_MIN_ALLOC(x,y,z) (__GMP_ABS(y->_mp_size)+__GMP_ABS(z->_mp_size)+1) +#define mpz_mul __gmpz_mul +__GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_mul_2exp __gmpz_mul_2exp +__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define __GMP_MPZ_MUL_SI_MIN_ALLOC(x,y,z) (__GMP_ABS(y->_mp_size)+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS+1) +#define mpz_mul_si __gmpz_mul_si +__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_si)); +#define __GMP_MPZ_MUL_UI_MIN_ALLOC(x,y,z) (__GMP_ABS(y->_mp_size)+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS+1) +#define mpz_mul_ui __gmpz_mul_ui +__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_neg __gmpz_neg +#define __GMP_MPZ_NEG_MIN_ALLOC(x,y) (__GMP_ABS(y->_mp_size)) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) +__GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif +#define mpz_nextprime __gmpz_nextprime +__GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#define mpz_next_prime_candidate __gmpz_next_prime_candidate +__GMP_DECLSPEC void mpz_next_prime_candidate __GMP_PROTO ((mpz_ptr, mpz_srcptr, gmp_randstate_t)); +#define mpz_out_raw __gmpz_out_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); +#endif +#define mpz_out_str __gmpz_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); +#endif +#define mpz_perfect_power_p __gmpz_perfect_power_p +__GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpz_perfect_square_p __gmpz_perfect_square_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) +__GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_popcount __gmpz_popcount +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) +__GMP_DECLSPEC mp_bitcnt_t mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_pow_ui __gmpz_pow_ui +__GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_powm __gmpz_powm +__GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); +#define mpz_powm_ui __gmpz_powm_ui +__GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui, mpz_srcptr)); +#define mpz_probab_prime_p __gmpz_probab_prime_p +__GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; +#define mpz_probable_prime_p __gmpz_probable_prime_p +__GMP_DECLSPEC int mpz_probable_prime_p __GMP_PROTO ((mpz_srcptr,gmp_randstate_t, int, mpir_ui)); +#define mpz_likely_prime_p __gmpz_likely_prime_p +__GMP_DECLSPEC int mpz_likely_prime_p __GMP_PROTO ((mpz_srcptr,gmp_randstate_t, mpir_ui)); +#define mpz_realloc2 __gmpz_realloc2 +__GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, mp_bitcnt_t)); +#define mpz_remove __gmpz_remove +__GMP_DECLSPEC mp_bitcnt_t mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_root __gmpz_root +__GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_nthroot __gmpz_nthroot +__GMP_DECLSPEC void mpz_nthroot __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_rootrem __gmpz_rootrem +__GMP_DECLSPEC void mpz_rootrem __GMP_PROTO ((mpz_ptr,mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_rrandomb __gmpz_rrandomb +__GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mp_bitcnt_t)); +#define mpz_scan0 __gmpz_scan0 +__GMP_DECLSPEC mp_bitcnt_t mpz_scan0 __GMP_PROTO ((mpz_srcptr, mp_bitcnt_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_scan1 __gmpz_scan1 +__GMP_DECLSPEC mp_bitcnt_t mpz_scan1 __GMP_PROTO ((mpz_srcptr, mp_bitcnt_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define __GMP_MPZ_SET_MIN_ALLOC(x,y) __GMP_ABS(y->_mp_size) +#define mpz_set __gmpz_set +__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#define mpz_set_d __gmpz_set_d +__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); +#define mpz_set_f __gmpz_set_f +__GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); +#define mpz_set_q __gmpz_set_q +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) +__GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +#endif +#define __GMP_MPZ_SET_SI_MIN_ALLOC(x,y) (1+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS) +#define mpz_set_si __gmpz_set_si +__GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, mpir_si)); +#define mpz_set_str __gmpz_set_str +__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); +#define __GMP_MPZ_SET_UI_MIN_ALLOC(x,y) (1+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS) +#define mpz_set_ui __gmpz_set_ui +__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, mpir_ui)); +#define mpz_setbit __gmpz_setbit +__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, mp_bitcnt_t)); +#define mpz_size __gmpz_size +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) +__GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpz_sizeinbase __gmpz_sizeinbase +__GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_sqrt __gmpz_sqrt +__GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#define mpz_sqrtrem __gmpz_sqrtrem +__GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); +#define __GMP_MPZ_SUB_MIN_ALLOC(x,y,z) (__GMP_MAX(__GMP_ABS(y->_mp_size),__GMP_ABS(z->_mp_size))+1) +#define mpz_sub __gmpz_sub +__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define __GMP_MPZ_SUB_UI_MIN_ALLOC(x,y,z) (__GMP_MAX(__GMP_ABS(y->_mp_size),1+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS)+1) +#define mpz_sub_ui __gmpz_sub_ui +__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define __GMP_MPZ_UI_SUB_MIN_ALLOC(x,y,z) (__GMP_MAX(__GMP_ABS(z->_mp_size),1+(GMP_BITS_PER_UI-1)/GMP_NUMB_BITS)+1) +#define mpz_ui_sub __gmpz_ui_sub +__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, mpir_ui, mpz_srcptr)); +#define mpz_submul __gmpz_submul +__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_submul_ui __gmpz_submul_ui +__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_swap __gmpz_swap +__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; +#define mpz_tdiv_ui __gmpz_tdiv_ui +__GMP_DECLSPEC mpir_ui mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpz_tdiv_q __gmpz_tdiv_q +__GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp +__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui +__GMP_DECLSPEC mpir_ui mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_tdiv_qr __gmpz_tdiv_qr +__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui +__GMP_DECLSPEC mpir_ui mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_tdiv_r __gmpz_tdiv_r +__GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp +__GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, mp_bitcnt_t)); +#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui +__GMP_DECLSPEC mpir_ui mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpir_ui)); +#define mpz_tstbit __gmpz_tstbit +__GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, mp_bitcnt_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpz_ui_pow_ui __gmpz_ui_pow_ui +__GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, mpir_ui, mpir_ui)); +#define mpz_urandomb __gmpz_urandomb +__GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mp_bitcnt_t)); +#define mpz_urandomm __gmpz_urandomm +__GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); +#define mpz_xor __gmpz_xor +#define mpz_eor __gmpz_xor +__GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +#define mpz_limbs_read __gmpz_limbs_read +__GMP_DECLSPEC mp_srcptr mpz_limbs_read (mpz_srcptr); +#define mpz_limbs_write __gmpz_limbs_write +__GMP_DECLSPEC mp_ptr mpz_limbs_write (mpz_ptr, mp_size_t); +#define mpz_limbs_modify __gmpz_limbs_modify +__GMP_DECLSPEC mp_ptr mpz_limbs_modify (mpz_ptr, mp_size_t); +#define mpz_limbs_finish __gmpz_limbs_finish +__GMP_DECLSPEC void mpz_limbs_finish (mpz_ptr, mp_size_t); +#define mpz_roinit_n __gmpz_roinit_n +__GMP_DECLSPEC mpz_srcptr mpz_roinit_n (mpz_ptr, mp_srcptr, mp_size_t); +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} +/****** Integer (i.e. Z) routines for intmaax_t/uintmax_t types ******/ +/* if stdint.h is available -- n.b: we do NOT include stdint.h ourselves */ +#if defined(INTMAX_MAX) +#define __GMP_BITS_PER_UINTMAX (8*sizeof(uintmax_t)) +#define mpz_get_ux __gmpz_get_ux +__GMP_DECLSPEC uintmax_t mpz_get_ux __GMP_PROTO ((mpz_srcptr)); +#define mpz_get_sx __gmpz_get_sx +__GMP_DECLSPEC intmax_t mpz_get_sx __GMP_PROTO ((mpz_srcptr)); +#define mpz_set_ux __gmpz_set_ux +__GMP_DECLSPEC void mpz_set_ux __GMP_PROTO ((mpz_ptr, uintmax_t)); +#define mpz_set_sx __gmpz_set_sx +__GMP_DECLSPEC void mpz_set_sx __GMP_PROTO ((mpz_ptr, intmax_t)); +#define mpz_init_set_ux __gmpz_init_set_ux +__GMP_DECLSPEC void mpz_init_set_ux __GMP_PROTO ((mpz_ptr, uintmax_t)); +#define mpz_init_set_sx __gmpz_init_set_sx +__GMP_DECLSPEC void mpz_init_set_sx __GMP_PROTO ((mpz_ptr, intmax_t)); +#endif +/**************** Rational (i.e. Q) routines. ****************/ +#define mpq_abs __gmpq_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) +__GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif +#define mpq_add __gmpq_add +__GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +#define mpq_canonicalize __gmpq_canonicalize +__GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); +#define mpq_clear __gmpq_clear +__GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); +#define mpq_clears __gmpq_clears +__GMP_DECLSPEC void mpq_clears __GMP_PROTO ((mpq_ptr, ...)); +#define mpq_cmp __gmpq_cmp +__GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; +#define _mpq_cmp_si __gmpq_cmp_si +__GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, mpir_si, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define _mpq_cmp_ui __gmpq_cmp_ui +__GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, mpir_ui, mpir_ui)) __GMP_ATTRIBUTE_PURE; +#define mpq_cmp_z __gmpq_cmp_z +__GMP_DECLSPEC int mpq_cmp_z (mpq_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; +#define mpq_div __gmpq_div +__GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +#define mpq_div_2exp __gmpq_div_2exp +__GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, mp_bitcnt_t)); +#define mpq_equal __gmpq_equal +__GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpq_get_num __gmpq_get_num +__GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +#define mpq_get_den __gmpq_get_den +__GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +#define mpq_get_d __gmpq_get_d +__GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpq_get_str __gmpq_get_str +__GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); +#define mpq_init __gmpq_init +__GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); +#define mpq_inits __gmpq_inits +__GMP_DECLSPEC void mpq_inits __GMP_PROTO ((mpq_ptr, ...)); +#define mpq_inp_str __gmpq_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); +#endif +#define mpq_inv __gmpq_inv +__GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#define mpq_mul __gmpq_mul +__GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +#define mpq_mul_2exp __gmpq_mul_2exp +__GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, mp_bitcnt_t)); +#define mpq_neg __gmpq_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) +__GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif +#define mpq_out_str __gmpq_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); +#endif +#define mpq_set __gmpq_set +__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#define mpq_set_d __gmpq_set_d +__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); +#define mpq_set_den __gmpq_set_den +__GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +#define mpq_set_f __gmpq_set_f +__GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); +#define mpq_set_num __gmpq_set_num +__GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +#define mpq_set_si __gmpq_set_si +__GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, mpir_si, mpir_ui)); +#define mpq_set_str __gmpq_set_str +__GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, __gmp_const char *, int)); +#define mpq_set_ui __gmpq_set_ui +__GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, mpir_ui, mpir_ui)); +#define mpq_set_z __gmpq_set_z +__GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +#define mpq_sub __gmpq_sub +__GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +#define mpq_swap __gmpq_swap +__GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; +/**************** Float (i.e. F) routines. ****************/ +#define mpf_abs __gmpf_abs +__GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_add __gmpf_add +__GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +#define mpf_add_ui __gmpf_add_ui +__GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpir_ui)); +#define mpf_ceil __gmpf_ceil +__GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_clear __gmpf_clear +__GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); +#define mpf_clears __gmpf_clears +__GMP_DECLSPEC void mpf_clears __GMP_PROTO ((mpf_ptr, ...)); +#define mpf_cmp __gmpf_cmp +__GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_cmp_d __gmpf_cmp_d +__GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; +#define mpf_cmp_si __gmpf_cmp_si +__GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, mpir_si)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_cmp_ui __gmpf_cmp_ui +__GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, mpir_ui)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_div __gmpf_div +__GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +#define mpf_div_2exp __gmpf_div_2exp +__GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, mp_bitcnt_t)); +#define mpf_div_ui __gmpf_div_ui +__GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpir_ui)); +#define mpf_dump __gmpf_dump +__GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); +#define mpf_eq __gmpf_eq +__GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, mp_bitcnt_t)) __GMP_ATTRIBUTE_PURE; +#define mpf_fits_sint_p __gmpf_fits_sint_p +__GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_si_p __gmpf_fits_si_p +__GMP_DECLSPEC int mpf_fits_si_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_slong_p __gmpf_fits_slong_p +__GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_sshort_p __gmpf_fits_sshort_p +__GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_uint_p __gmpf_fits_uint_p +__GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_ui_p __gmpf_fits_ui_p +__GMP_DECLSPEC int mpf_fits_ui_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_ulong_p __gmpf_fits_ulong_p +__GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_fits_ushort_p __gmpf_fits_ushort_p +__GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_floor __gmpf_floor +__GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_get_d __gmpf_get_d +__GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; +#define mpf_get_d_2exp __gmpf_get_d_2exp +__GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long *, mpf_srcptr)); +#define mpf_get_default_prec __gmpf_get_default_prec +__GMP_DECLSPEC mp_bitcnt_t mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_get_prec __gmpf_get_prec +__GMP_DECLSPEC mp_bitcnt_t mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_get_si __gmpf_get_si +__GMP_DECLSPEC mpir_si mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_get_str __gmpf_get_str +__GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); +#define mpf_get_ui __gmpf_get_ui +__GMP_DECLSPEC mpir_ui mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_init __gmpf_init +__GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); +#define mpf_init2 __gmpf_init2 +__GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, mp_bitcnt_t)); +#define mpf_inits __gmpf_inits +__GMP_DECLSPEC void mpf_inits __GMP_PROTO ((mpf_ptr, ...)); +#define mpf_init_set __gmpf_init_set +__GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_init_set_d __gmpf_init_set_d +__GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); +#define mpf_init_set_si __gmpf_init_set_si +__GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, mpir_si)); +#define mpf_init_set_str __gmpf_init_set_str +__GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); +#define mpf_init_set_ui __gmpf_init_set_ui +__GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, mpir_ui)); +#define mpf_inp_str __gmpf_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); +#endif +#define mpf_integer_p __gmpf_integer_p +__GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_mul __gmpf_mul +__GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +#define mpf_mul_2exp __gmpf_mul_2exp +__GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, mp_bitcnt_t)); +#define mpf_mul_ui __gmpf_mul_ui +__GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpir_ui)); +#define mpf_neg __gmpf_neg +__GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_out_str __gmpf_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); +#endif +#define mpf_pow_ui __gmpf_pow_ui +__GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpir_ui)); +#define mpf_random2 __gmpf_random2 +__GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); +#define mpf_rrandomb __gmpf_rrandomb +__GMP_DECLSPEC void mpf_rrandomb __GMP_PROTO ((mpf_ptr, gmp_randstate_t, mp_size_t, mp_exp_t)); +#define mpf_reldiff __gmpf_reldiff +__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +#define mpf_set __gmpf_set +__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_set_d __gmpf_set_d +__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); +#define mpf_set_default_prec __gmpf_set_default_prec +__GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((mp_bitcnt_t)) __GMP_NOTHROW; +#define mpf_set_prec __gmpf_set_prec +__GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, mp_bitcnt_t)); +#define mpf_set_prec_raw __gmpf_set_prec_raw +__GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, mp_bitcnt_t)) __GMP_NOTHROW; +#define mpf_set_q __gmpf_set_q +__GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); +#define mpf_set_si __gmpf_set_si +__GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, mpir_si)); +#define mpf_set_str __gmpf_set_str +__GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); +#define mpf_set_ui __gmpf_set_ui +__GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, mpir_ui)); +#define mpf_set_z __gmpf_set_z +__GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); +#define mpf_size __gmpf_size +__GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpf_sqrt __gmpf_sqrt +__GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_sqrt_ui __gmpf_sqrt_ui +__GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, mpir_ui)); +#define mpf_sub __gmpf_sub +__GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +#define mpf_sub_ui __gmpf_sub_ui +__GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpir_ui)); +#define mpf_swap __gmpf_swap +__GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; +#define mpf_trunc __gmpf_trunc +__GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +#define mpf_ui_div __gmpf_ui_div +__GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, mpir_ui, mpf_srcptr)); +#define mpf_ui_sub __gmpf_ui_sub +__GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, mpir_ui, mpf_srcptr)); +#define mpf_urandomb __gmpf_urandomb +__GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, mp_bitcnt_t)); +/************ Low level positive-integer (i.e. N) routines. ************/ +/* This is ugly, but we need to make user calls reach the prefixed function. */ +#define mpn_add __MPN(add) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) +__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif +#define mpn_add_1 __MPN(add_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) +__GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif +#define mpn_add_n __MPN(add_n) +__GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_addmul_1 __MPN(addmul_1) +__GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +#define mpn_bdivmod __MPN(bdivmod) +__GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mpir_ui)); +#define mpn_divrem __MPN(divrem) +__GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); +#define mpn_mulmod_Bexpp1 __MPN(mulmod_Bexpp1) +__GMP_DECLSPEC int mpn_mulmod_Bexpp1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_ptr)); +#define mpn_mulmod_2expp1 __MPN(mulmod_2expp1_basecase) +__GMP_DECLSPEC int mpn_mulmod_2expp1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr,int,mpir_ui, mp_ptr)); +#define mpn_mulmod_2expm1 __MPN(mulmod_2expm1) +__GMP_DECLSPEC void mpn_mulmod_2expm1 __GMP_PROTO ((mp_ptr, mp_ptr, mp_ptr, mpir_ui, mp_ptr)); +#define mpn_cmp __MPN(cmp) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) +__GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif +#define mpn_redc_1 __MPN(redc_1) +__GMP_DECLSPEC void mpn_redc_1 __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);) +#define mpn_redc_2 __MPN(redc_2) +__GMP_DECLSPEC void mpn_redc_2 __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr)); +#define mpn_redc_n __MPN(redc_n) +__GMP_DECLSPEC void mpn_redc_n __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr)); +#define mpn_divexact_by3(dst,src,size) \ + mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) +#define mpn_divexact_by3c __MPN(divexact_by3c) +__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +#define mpn_divmod_1(qp,np,nsize,dlimb) \ + mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) +#define mpn_divrem_1 __MPN(divrem_1) +__GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); +#define mpn_divrem_2 __MPN(divrem_2) +__GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); +#define mpn_invert __MPN(invert) +__GMP_DECLSPEC void mpn_invert __GMP_PROTO ((mp_ptr xp, mp_srcptr ap, mp_size_t n)); +#define mpn_sb_divappr_q __MPN(sb_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_sb_divappr_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dip)); +#define mpn_dc_bdiv_q_n __MPN(dc_bdiv_q_n) +__GMP_DECLSPEC void mpn_dc_bdiv_q_n __GMP_PROTO ((mp_ptr qp, mp_ptr wp, mp_ptr np, mp_srcptr dp, mp_size_t n, + mp_limb_t dinv, mp_ptr scratch)); +#define mpn_inv_divappr_q_n __MPN(inv_divappr_q_n) +__GMP_DECLSPEC mp_limb_t mpn_inv_divappr_q_n __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_srcptr dp, mp_size_t n, + mp_srcptr dip)); +#define mpn_dc_divappr_q __MPN(dc_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_dc_divappr_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, + mp_size_t n, mp_limb_t dinv)); +#define mpn_dc_div_q __MPN(dc_div_q) +__GMP_DECLSPEC mp_limb_t mpn_dc_div_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_inv_divappr_q __MPN(inv_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_inv_divappr_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t n, + mp_srcptr dinv)); +#define mpn_inv_div_q __MPN(inv_div_q) +__GMP_DECLSPEC mp_limb_t mpn_inv_div_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_srcptr dinv)); +#define mpn_inv_div_qr __MPN(inv_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_inv_div_qr __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_srcptr dinv)); +#define mpn_inv_div_qr_n __MPN(inv_div_qr_n) +__GMP_DECLSPEC mp_limb_t mpn_inv_div_qr_n __GMP_PROTO ((mp_ptr qp, mp_ptr np, + mp_srcptr dp, mp_size_t dn, mp_srcptr dinv)); +#define mpn_dc_div_qr __MPN(dc_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_dc_div_qr __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_dc_div_qr_n __MPN(dc_div_qr_n) +__GMP_DECLSPEC mp_limb_t mpn_dc_div_qr_n __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_srcptr dp, mp_size_t n, + mp_limb_t dinv, mp_ptr tp)); +#define mpn_sb_div_q __MPN(sb_div_q) +__GMP_DECLSPEC mp_limb_t mpn_sb_div_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_sb_bdiv_q __MPN(sb_bdiv_q) +__GMP_DECLSPEC void mpn_sb_bdiv_q __GMP_PROTO ((mp_ptr qp, mp_ptr wp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_dc_bdiv_q __MPN(dc_bdiv_q) +__GMP_DECLSPEC void mpn_dc_bdiv_q __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_dc_bdiv_qr __MPN(dc_bdiv_qr) +__GMP_DECLSPEC mp_limb_t mpn_dc_bdiv_qr __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_dc_bdiv_qr_n __MPN(dc_bdiv_qr_n) +__GMP_DECLSPEC mp_limb_t mpn_dc_bdiv_qr_n __GMP_PROTO ((mp_ptr qp, mp_ptr np, + mp_srcptr dp, mp_size_t n, mp_limb_t dinv, mp_ptr tp)); +#define mpn_sb_div_qr __MPN(sb_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_sb_div_qr __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_sb_bdiv_qr __MPN(sb_bdiv_qr) +__GMP_DECLSPEC mp_limb_t mpn_sb_bdiv_qr __GMP_PROTO ((mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, mp_limb_t dinv)); +#define mpn_tdiv_q __MPN(tdiv_q) +__GMP_DECLSPEC void mpn_tdiv_q __GMP_PROTO ((mp_ptr qp, mp_srcptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn)); +#define mpn_divexact __MPN(divexact) +__GMP_DECLSPEC void mpn_divexact __GMP_PROTO ((mp_ptr qp, + mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)); +#define mpn_gcd __MPN(gcd) +__GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +#define mpn_gcd_1 __MPN(gcd_1) +__GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +#define mpn_gcdext_1 __MPN(gcdext_1) +__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 __GMP_PROTO ((mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t)); +#define mpn_gcdext __MPN(gcdext) +__GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +#define mpn_get_str __MPN(get_str) +__GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); +#define mpn_hamdist __MPN(hamdist) +__GMP_DECLSPEC mp_bitcnt_t mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpn_lshift __MPN(lshift) +__GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +#define mpn_mod_1 __MPN(mod_1) +__GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +#define mpn_mul __MPN(mul) +__GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +#define mpn_mul_1 __MPN(mul_1) +__GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +#define mpn_mul_n __MPN(mul_n) +__GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_sqr __MPN(sqr) +__GMP_DECLSPEC void mpn_sqr __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_neg_n __MPN(neg_n) +#define mpn_neg __MPN(neg_n) +__GMP_DECLSPEC mp_limb_t mpn_neg_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_com_n __MPN(com_n) +#define mpn_com __MPN(com_n) +__GMP_DECLSPEC void mpn_com_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_perfect_square_p __MPN(perfect_square_p) +__GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; +#define mpn_popcount __MPN(popcount) +__GMP_DECLSPEC mp_bitcnt_t mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#define mpn_pow_1 __MPN(pow_1) +__GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); +/* undocumented now, but retained here for upward compatibility */ +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) +__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +#define mpn_random __MPN(random) +__GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); +#define mpn_random2 __MPN(random2) +__GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); +#define mpn_urandomb __MPN(urandomb) +__GMP_DECLSPEC void mpn_urandomb __GMP_PROTO ((mp_ptr, gmp_randstate_t, mpir_ui)); +#define mpn_urandomm __MPN(urandomm) +__GMP_DECLSPEC void mpn_urandomm __GMP_PROTO ((mp_ptr, gmp_randstate_t, mp_srcptr, mp_size_t)); +#define mpn_randomb __MPN(randomb) +__GMP_DECLSPEC void mpn_randomb __GMP_PROTO ((mp_ptr, gmp_randstate_t, mp_size_t)); +#define mpn_rrandom __MPN(rrandom) +__GMP_DECLSPEC void mpn_rrandom __GMP_PROTO ((mp_ptr, gmp_randstate_t, mp_size_t)); +#define mpn_rshift __MPN(rshift) +__GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +#define mpn_scan0 __MPN(scan0) +__GMP_DECLSPEC mp_bitcnt_t mpn_scan0 __GMP_PROTO ((mp_srcptr, mp_bitcnt_t)) __GMP_ATTRIBUTE_PURE; +#define mpn_scan1 __MPN(scan1) +__GMP_DECLSPEC mp_bitcnt_t mpn_scan1 __GMP_PROTO ((mp_srcptr, mp_bitcnt_t)) __GMP_ATTRIBUTE_PURE; +#define mpn_set_str __MPN(set_str) +__GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); +#define mpn_sizeinbase __MPN(sizeinbase) +__GMP_DECLSPEC size_t mpn_sizeinbase (mp_srcptr, mp_size_t, int); +#define mpn_sqrtrem __MPN(sqrtrem) +__GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_sub __MPN(sub) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) +__GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif +#define mpn_sub_1 __MPN(sub_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) +__GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif +#define mpn_sub_n __MPN(sub_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_submul_1 __MPN(submul_1) +__GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +#define mpn_tdiv_qr __MPN(tdiv_qr) +__GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +#define mpn_and_n __MPN(and_n) +__GMP_DECLSPEC void mpn_and_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_andn_n __MPN(andn_n) +__GMP_DECLSPEC void mpn_andn_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_nand_n __MPN(nand_n) +__GMP_DECLSPEC void mpn_nand_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_ior_n __MPN(ior_n) +__GMP_DECLSPEC void mpn_ior_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_iorn_n __MPN(iorn_n) +__GMP_DECLSPEC void mpn_iorn_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_nior_n __MPN(nior_n) +__GMP_DECLSPEC void mpn_nior_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_xor_n __MPN(xor_n) +__GMP_DECLSPEC void mpn_xor_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_xnor_n __MPN(xnor_n) +__GMP_DECLSPEC void mpn_xnor_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#define mpn_copyi __MPN(copyi) +__GMP_DECLSPEC void mpn_copyi __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_copyd __MPN(copyd) +__GMP_DECLSPEC void mpn_copyd __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_zero __MPN(zero) +__GMP_DECLSPEC void mpn_zero __GMP_PROTO ((mp_ptr, mp_size_t)); +#ifndef mpn_sumdiff_n /* if not done with cpuvec in a fat binary of in gmp-impl.h*/ +#define mpn_sumdiff_n __MPN(sumdiff_n) +__GMP_DECLSPEC mp_limb_t mpn_sumdiff_n __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#endif +#ifndef mpn_nsumdiff_n /* if not done with cpuvec in a fat binary of in gmp-impl.h*/ +#define mpn_nsumdiff_n __MPN(nsumdiff_n) +__GMP_DECLSPEC mp_limb_t mpn_nsumdiff_n __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +#endif +/**************** MPN API for FFT ****************/ +#define mpn_mul_fft_main __MPN(mul_fft_main) +__GMP_DECLSPEC void mpn_mul_fft_main __GMP_PROTO ((mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2)); +#define mpn_mul_fft __MPN(mul_fft) +__GMP_DECLSPEC int mpn_mul_fft __GMP_PROTO((mp_ptr rp, mp_size_t rn, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn, int k)); +/**************** mpz inlines ****************/ +/* The following are provided as inlines where possible, but always exist as + library functions too, for binary compatibility. + Within gmp itself this inlining generally isn't relied on, since it + doesn't get done for all compilers, whereas if something is worth + inlining then it's worth arranging always. + There are two styles of inlining here. When the same bit of code is + wanted for the inline as for the library version, then __GMP_FORCE_foo + arranges for that code to be emitted and the __GMP_EXTERN_INLINE + directive suppressed, eg. mpz_fits_uint_p. When a different bit of code + is wanted for the inline than for the library version, then + __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs) +__GMP_EXTERN_INLINE void +mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); +} +#endif +#if GMP_NAIL_BITS == 0 +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); +#else +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ + || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) +#if ! defined (__GMP_FORCE_mpz_fits_uint_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ui_p) +#if ! defined (__GMP_FORCE_mpz_fits_ui_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ui_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, GMP_UI_MAX); +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ulong_p) +#if ! defined (__GMP_FORCE_mpz_fits_ulong_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ushort_p) +#if ! defined (__GMP_FORCE_mpz_fits_ushort_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_get_ui) +#if ! defined (__GMP_FORCE_mpz_get_ui) +__GMP_EXTERN_INLINE +#endif +mpir_ui +mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + mp_ptr __gmp_p = __gmp_z->_mp_d; + mp_size_t __gmp_n = __gmp_z->_mp_size; + mp_limb_t __gmp_l = __gmp_p[0]; + /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings + about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland + C++ 6.0 warnings about condition always true for something like + "__GMP_ULONG_MAX < GMP_NUMB_MASK". */ +#if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) + /* limb==long and no nails, or limb==longlong, one limb is enough */ + return (mpir_ui)(__gmp_n != 0 ? __gmp_l : 0); +#else + /* limb==long and nails, need two limbs when available */ + __gmp_n = __GMP_ABS (__gmp_n); + if (__gmp_n <= 1) + return (mpir_ui)(__gmp_n != 0 ? __gmp_l : 0); + else + return (mpir_ui)(__gmp_l + (__gmp_p[1] << GMP_NUMB_BITS)); +#endif +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_getlimbn) +#if ! defined (__GMP_FORCE_mpz_getlimbn) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_result = 0; + if (__GMP_LIKELY (__gmp_n >= 0 && __gmp_n < __GMP_ABS (__gmp_z->_mp_size))) + __gmp_result = __gmp_z->_mp_d[__gmp_n]; + return __gmp_result; +} +#endif +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_neg) +__GMP_EXTERN_INLINE void +mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = - __gmp_w->_mp_size; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_perfect_square_p) +#if ! defined (__GMP_FORCE_mpz_perfect_square_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_perfect_square_p (mpz_srcptr __gmp_a) +{ + mp_size_t __gmp_asize; + int __gmp_result; + __gmp_asize = __gmp_a->_mp_size; + __gmp_result = (__gmp_asize >= 0); /* zero is a square, negatives are not */ + if (__GMP_LIKELY (__gmp_asize > 0)) + __gmp_result = mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); + return __gmp_result; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_popcount) +#if ! defined (__GMP_FORCE_mpz_popcount) +__GMP_EXTERN_INLINE +#endif +mp_bitcnt_t +mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW +{ + mp_size_t __gmp_usize; + mp_bitcnt_t __gmp_result; + __gmp_usize = __gmp_u->_mp_size; + __gmp_result = (__gmp_usize < 0 ? __GMP_BITCNT_MAX : 0); + if (__GMP_LIKELY (__gmp_usize > 0)) + __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); + return __gmp_result; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_set_q) +#if ! defined (__GMP_FORCE_mpz_set_q) +__GMP_EXTERN_INLINE +#endif +void +mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_size) +#if ! defined (__GMP_FORCE_mpz_size) +__GMP_EXTERN_INLINE +#endif +size_t +mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + return __GMP_ABS (__gmp_z->_mp_size); +} +#endif +/**************** mpq inlines ****************/ +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_abs) +__GMP_EXTERN_INLINE void +mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); +} +#endif +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_neg) +__GMP_EXTERN_INLINE void +mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; +} +#endif +/**************** mpn inlines ****************/ +/* The comments with __GMPN_ADD_1 below apply here too. + The test for FUNCTION returning 0 should predict well. If it's assumed + {yp,ysize} will usually have a random number of bits then the high limb + won't be full and a carry out will occur a good deal less than 50% of the + time. + ysize==0 isn't a documented feature, but is used internally in a few + places. + Producing cout last stops it using up a register during the main part of + the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" + doesn't seem able to move the true and false legs of the conditional up + to the two places cout is generated. */ +#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x; \ + \ + /* ASSERT ((ysize) >= 0); */ \ + /* ASSERT ((xsize) >= (ysize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ + \ + __gmp_i = (ysize); \ + if (__gmp_i != 0) \ + { \ + if (FUNCTION (wp, xp, yp, __gmp_i)) \ + { \ + do \ + { \ + if (__gmp_i >= (xsize)) \ + { \ + (cout) = 1; \ + goto __gmp_done; \ + } \ + __gmp_x = (xp)[__gmp_i]; \ + } \ + while (TEST); \ + } \ + } \ + if ((wp) != (xp)) \ + __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ + (cout) = 0; \ + __gmp_done: \ + ; \ + } while (0) +#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ + (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) +#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ + (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) +/* The use of __gmp_i indexing is designed to ensure a compile time src==dst + remains nice and clear to the compiler, so that __GMPN_COPY_REST can + disappear, and the load/add/store gets a chance to become a + read-modify-write on CISC CPUs. + Alternatives: + Using a pair of pointers instead of indexing would be possible, but gcc + isn't able to recognise compile-time src==dst in that case, even when the + pointers are incremented more or less together. Other compilers would + very likely have similar difficulty. + gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or + similar to detect a compile-time src==dst. This works nicely on gcc + 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems + to be always false, for a pointer p. But the current code form seems + good enough for src==dst anyway. + gcc on x86 as usual doesn't give particularly good flags handling for the + carry/borrow detection. It's tempting to want some multi instruction asm + blocks to help it, and this was tried, but in truth there's only a few + instructions to save and any gain is all too easily lost by register + juggling setting up for the asm. */ +#if GMP_NAIL_BITS == 0 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r; \ + if (CB (__gmp_r, __gmp_x, (v))) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r; \ + ++__gmp_i; \ + if (!CB (__gmp_r, __gmp_x, 1)) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif +#if GMP_NAIL_BITS >= 1 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ + if (__gmp_r >> GMP_NUMB_BITS != 0) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ + ++__gmp_i; \ + if (__gmp_r >> GMP_NUMB_BITS == 0) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif +#define __GMPN_ADDCB(r,x,y) ((r) < (y)) +#define __GMPN_SUBCB(r,x,y) ((x) < (y)) +#define __GMPN_ADD_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) +#define __GMPN_SUB_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) +/* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or + negative. size==0 is allowed. On random data usually only one limb will + need to be examined to get a result, so it's worth having it inline. */ +#define __GMPN_CMP(result, xp, yp, size) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_y; \ + \ + /* ASSERT ((size) >= 0); */ \ + \ + (result) = 0; \ + __gmp_i = (size); \ + while (--__gmp_i >= 0) \ + { \ + __gmp_x = (xp)[__gmp_i]; \ + __gmp_y = (yp)[__gmp_i]; \ + if (__gmp_x != __gmp_y) \ + { \ + /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ + (result) = (__gmp_x > __gmp_y ? 1 : -1); \ + break; \ + } \ + } \ + } while (0) +#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ + } while (0) +#endif +/* Copy {src,size} to {dst,size}, starting at "start". This is designed to + keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, + __GMPN_ADD, etc. */ +#if ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + mp_size_t __gmp_j; \ + /* ASSERT ((size) >= 0); */ \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ + for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ + (dst)[__gmp_j] = (src)[__gmp_j]; \ + } while (0) +#endif +/* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use + mpn_copyi if there's a native version, and if we don't mind demanding + binary compatibility for it (on targets which use it). */ +#if ! defined (__GMPN_COPY) +#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add) +#if ! defined (__GMP_FORCE_mpn_add) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add_1) +#if ! defined (__GMP_FORCE_mpn_add_1) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_cmp) +#if ! defined (__GMP_FORCE_mpn_cmp) +__GMP_EXTERN_INLINE +#endif +int +mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW +{ + int __gmp_result; + __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); + return __gmp_result; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) +#if ! defined (__GMP_FORCE_mpn_sub) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub_1) +#if ! defined (__GMP_FORCE_mpn_sub_1) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif +#if defined (__cplusplus) +} +#endif +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (SI) && (SI) > 0 \ + ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ + : _mpz_cmp_si (Z,SI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ + ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ + : _mpq_cmp_si (q, n, d)) +#else +#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) +#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) +#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) +#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) +#endif +/* Using "&" rather than "&&" means these can come out branch-free. Every + mpz_t has at least one limb allocated, so fetching the low limb is always + allowed. */ +#define mpz_odd_p(z) (((z)->_mp_size != 0) & __GMP_CAST (int, (z)->_mp_d[0])) +#define mpz_even_p(z) (! mpz_odd_p (z)) +/**************** C++ routines ****************/ +#ifdef __cplusplus +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); +#endif +/* Source-level compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) +#define gmp_randinit(x,y,z) gmp_randinit_lc_2exp_size(x,z) +typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ +typedef __mpq_struct MP_RAT; /* gmp 1 source compatibility */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp +enum +{ + GMP_ERROR_NONE = 0, + GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, + GMP_ERROR_DIVISION_BY_ZERO = 2, + GMP_ERROR_SQRT_OF_NEGATIVE = 4, + GMP_ERROR_INVALID_ARGUMENT = 8 +}; +/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ +#define __GNU_MP_VERSION 6 +#define __GNU_MP_VERSION_MINOR 0 +#define __GNU_MP_VERSION_PATCHLEVEL 0 +#define GMP_VERSION "6.0.0" +#define __GNU_MP_RELEASE (__GNU_MP_VERSION * 10000 + __GNU_MP_VERSION_MINOR * 100 + __GNU_MP_VERSION_PATCHLEVEL) +#define __MPIR_VERSION 3 +#define __MPIR_VERSION_MINOR 0 +#define __MPIR_VERSION_PATCHLEVEL 0 +#if defined( _MSC_VER ) +#define _MSC_MPIR_VERSION "3.0.0" +#endif +#define __MPIR_RELEASE (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL) +/* These are for programs like MPFR to use the same CC and CFLAGS as MPIR */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +#endif +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/mpir/mpir-2017.lib b/mpir/mpir-2017.lib new file mode 100644 index 0000000..fa7b0bc Binary files /dev/null and b/mpir/mpir-2017.lib differ diff --git a/nmakefile b/nmakefile deleted file mode 100644 index 643433c..0000000 --- a/nmakefile +++ /dev/null @@ -1,8 +0,0 @@ -TARGET = me7sum.exe -SOURCES = crc32.c inifile_prop.c me7sum.c utils.c inifile/inifile.c -all: $(TARGET) -$(TARGET):$(SOURCES) - cl /EHsc /Fe$@ $(SOURCES) - -clean: - del $(TARGET) *.obj diff --git a/os/getopt.h b/os/getopt.h new file mode 100644 index 0000000..55045f5 --- /dev/null +++ b/os/getopt.h @@ -0,0 +1,11 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +#include "pgetopt.h" +#define getopt pgetopt +#define opterr popterr /* popterr does the WRONG thing? */ +#define optind poptind +#define optarg poptarg +#define optopt poptopt + +#endif diff --git a/os/mmap.h b/os/mmap.h deleted file mode 100644 index 5f1437f..0000000 --- a/os/mmap.h +++ /dev/null @@ -1,10 +0,0 @@ -#include - -#define PROT_READ 0x1 -#define PROT_WRITE 0x2 -#define MAP_SHARED 0x1 - -#define MAP_FAILED ((void *) -1) - -void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); -int munmap(void *addr, size_t length); diff --git a/os/os.h b/os/os.h new file mode 100644 index 0000000..77c5a61 --- /dev/null +++ b/os/os.h @@ -0,0 +1,17 @@ +#ifndef _OS_H +#define _OS_H + +#if _WIN32 +#include "getopt.h" +#include +#include /* ntohl() */ +#else // ! _WIN32 + +#ifdef __GNUC__ +#include +#include /* ntohl() */ +#endif + +#endif // ! _WIN32 + +#endif diff --git a/os/pgetopt.c b/os/pgetopt.c new file mode 100644 index 0000000..9851488 --- /dev/null +++ b/os/pgetopt.c @@ -0,0 +1,233 @@ +/* + * pgetopt.c - Portable implementation of getopt() command line args parser, + * originally made available by IBM and the authors listed below. + * + * Created on 8/8/08. + * Portions of this document are Copyright (C) 2008, PlexFX, + * All Rights Reserved. + * + * History: + * Original Date Unknown + * This code is quite old, but it was originally called GETOPT.C + * in the comments, along with a GETOPT.H thin header, and used the + * same namespace as the getopt() implementation on my UNIX variant + * platforms. The original date has been lost. It may date back + * to even pre-ANSI C. The development team at PlexFX has been + * using it (primarily for Windows command line tools, but also on + * other platforms for many years. A search for historical dates + * via web search engines found it widely used, but no date stamps + * on its original form seem to have been preserved. + * It can be found in various forms in open source packages, such + * as using a search engine on one or both of the author strings + * shown in the original comment block below. For example, as of + * the creation date on this file, a slightly modified verion of + * it was used in library code found in the CVS tree for + * OpenSolaris. + * + * It was also included on at least some of the MSDN Library discs + * Around the early 2001-2003 time frame. + * + * 2008-08-08 This version is a modified version of the original IBM code, but + * the filename and namespace used has been altered along with some + * calling convention changes. As such, it can be used as a drop- + * in replacement for getopt() even on UNIX or Linux systems that + * have their own getopt() implementations in libc without naming + * collisions. This means it can be used portably on any OS with + * a conforming C compiler. It does *not* attempt to implement the + * more long-winded getopt_long() interface. Naming of APIs, + * headers and the optarg/optind externs have been prefixed with + * 'p' to accomplish this. Examples: pgetopt(), poptarg, poptind, + * pgetopt.c, pgetopt.h. + * Note: This interface keeps external state (to match original + * calling conventions). As such, it is not thread safe, + * and should be called in only one thread (use from main() + * before additional threads are started). As the command + * line should never change, this should not be an issue. + * + */ + +/* Original IBM "AS IS" license follows */ + +/***************************************************************************** + * + * MODULE NAME : GETOPT.C + * + * COPYRIGHTS: + * This module contains code made available by IBM + * Corporation on an AS IS basis. Any one receiving the + * module is considered to be licensed under IBM copyrights + * to use the IBM-provided source code in any way he or she + * deems fit, including copying it, compiling it, modifying + * it, and redistributing it, with or without + * modifications. No license under any IBM patents or + * patent applications is to be implied from this copyright + * license. + * + * A user of the module should understand that IBM cannot + * provide technical support for the module and will not be + * responsible for any consequences of use of the program. + * + * Any notices, including this one, are not to be removed + * from the module without the prior written consent of + * IBM. + * + * AUTHOR: Original author: + * G. R. Blair (BOBBLAIR at AUSVM1) + * Internet: bobblair@bobblair.austin.ibm.com + * + * Extensively revised by: + * John Q. Walker II, Ph.D. (JOHHQ at RALVM6) + * Internet: johnq@ralvm6.vnet.ibm.com + * + *****************************************************************************/ + +/****************************************************************************** + * pgetopt() + * + * The pgetopt() function is a command line parser. It returns the next + * option character in argv that matches an option character in optstring. + * + * The argv argument points to an array of argc+1 elements containing argc + * pointers to character strings followed by a null pointer. + * + * The optstring argument points to a string of option characters; if an + * option character is followed by a colon, the option is expected to have + * an argument that may or may not be separated from it by white space. + * The external variable poptarg is set to point to the start of the option + * argument on return from pgetopt(). + * + * The pgetopt() function places in poptind the argv index of the next argument + * to be processed. The system initializes the external variable poptind to + * 1 before the first call to pgetopt(). + * + * When all options have been processed (that is, up to the first nonoption + * argument), pgetopt() returns -1. The special option "--" may be used to + * delimit the end of the options; -1 will be returned, and "--" will be + * skipped. + * + * The pgetopt() function returns a question mark (?) when it encounters an + * option character not included in optstring. This error message can be + * disabled by setting popterr to zero. Otherwise, it returns the option + * character that was detected. + * + * If the special option "--" is detected, or all options have been + * processed, -1 is returned. + * + * Options are marked by either a minus sign (-) or a slash (/). + * + * No other errors are defined. + *****************************************************************************/ + +//#include /* for EOF */ +#include /* for strchr() */ +#include "pgetopt.h" /* pgetopt() interface and example code */ + +/* global variables that are specified as exported by pgetopt() */ +char *poptarg = NULL; /* pointer to the start of the option argument */ +int poptind = 1; /* number of the next argv[] to be evaluated */ +int popterr = 1; /* non-zero if a question mark should be returned + * when a non-valid option character is detected */ +int poptopt = 0; /* original opt when we return ? */ + +/* handle possible future character set concerns by putting this in a macro */ +#define _next_char(string) (char)(*(string+1)) + +int +pgetopt(int argc, char *argv[], char *optstring) +{ + static char *IndexPosition = NULL; /* place inside current argv string */ + char *ArgString = NULL; /* where to start from next */ + char *OptString; /* the string in our program */ + + + if (IndexPosition != NULL) { + /* we last left off inside an argv string */ + if (*(++IndexPosition)) { + /* there is more to come in the most recent argv */ + ArgString = IndexPosition; + } + } + + if (ArgString == NULL) { + /* we didn't leave off in the middle of an argv string */ + if (poptind >= argc) { + /* more command-line arguments than the argument count */ + IndexPosition = NULL; /* not in the middle of anything */ + return -1; /* used up all command-line arguments */ + } + + /*--------------------------------------------------------------------- + * If the next argv[] is not an option, there can be no more options. + *-------------------------------------------------------------------*/ + ArgString = argv[poptind++]; /* set this to the next argument ptr */ + + if (('/' != *ArgString) && /* doesn't start with a slash or a dash? */ + ('-' != *ArgString)) { + --poptind; /* point to current arg once we're done */ + poptarg = NULL; /* no argument follows the option */ + IndexPosition = NULL; /* not in the middle of anything */ + return -1; /* used up all the command-line flags */ + } + + /* check for special end-of-flags markers */ + if ((strcmp(ArgString, "-") == 0) || + (strcmp(ArgString, "--") == 0)) { + poptarg = NULL; /* no argument follows the option */ + IndexPosition = NULL; /* not in the middle of anything */ + return -1; /* encountered the special flag */ + } + + ArgString++; /* look past the / or - */ + } + + if (':' == *ArgString) { /* is it a colon? */ + /*--------------------------------------------------------------------- + * Rare case: if opterr is non-zero, return a question mark; + * otherwise, just return the colon we're on. + *-------------------------------------------------------------------*/ + return (popterr ? (int)'?' : (int)':'); + } + else if ((OptString = strchr(optstring, *ArgString)) == 0) { + /*--------------------------------------------------------------------- + * The letter on the command-line wasn't any good. + *-------------------------------------------------------------------*/ + poptarg = NULL; /* no argument follows the option */ + IndexPosition = NULL; /* not in the middle of anything */ + poptopt = (int)*ArgString; + return (popterr ? (int)'?' : (int)*ArgString); + } + else { + /*--------------------------------------------------------------------- + * The letter on the command-line matches one we expect to see + *-------------------------------------------------------------------*/ + if (':' == _next_char(OptString)) { /* is the next letter a colon? */ + /* It is a colon. Look for an argument string. */ + if ('\0' != _next_char(ArgString)) { /* argument in this argv? */ + poptarg = &ArgString[1]; /* Yes, it is */ + } + else { + /*------------------------------------------------------------- + * The argument string must be in the next argv. + * But, what if there is none (bad input from the user)? + * In that case, return the letter, and poptarg as NULL. + *-----------------------------------------------------------*/ + if (poptind < argc) + poptarg = argv[poptind++]; + else { + poptarg = NULL; + poptopt = (int)*ArgString; + return (popterr ? (int)'?' : (int)*ArgString); + } + } + IndexPosition = NULL; /* not in the middle of anything */ + } + else { + /* it's not a colon, so just return the letter */ + poptarg = NULL; /* no argument follows the option */ + IndexPosition = ArgString; /* point to the letter we're on */ + } + return (int)*ArgString; /* return the letter that matched */ + } +} + + diff --git a/os/pgetopt.h b/os/pgetopt.h new file mode 100644 index 0000000..7b1fe53 --- /dev/null +++ b/os/pgetopt.h @@ -0,0 +1,135 @@ +/* + * pgetopt.h - Portable implementation of getopt() command line args parser, + * originally made available by IBM and the authors listed below. + * + * Created on 8/8/08. + * Portions of this document are Copyright (C) 2008, PlexFX, + * All Rights Reserved. + * + * History: + * Original Date Unknown + * This code is quite old, but it was originally called GETOPT.H + * in the comments, along with a GETOPT.C source file, and used the + * same namespace as the getopt() implementation on my UNIX variant + * platforms. The original date has been lost. It may date back + * to even pre-ANSI C. The development team at PlexFX has been + * using it (primarily for Windows command line tools, but also on + * other platforms for many years. A search for historical dates + * via web search engines found it widely used, but no date stamps + * on its original form seem to have been preserved. + * It can be found in various forms in open source packages, such + * as using a search engine on one or both of the author strings + * shown in the original comment block below. For example, as of + * the creation date on this file, a slightly modified verion of + * it was used in library code found in the CVS tree for + * OpenSolaris. + * + * It was also included on at least some of the MSDN Library discs + * Around the early 2001-2003 time frame. + * + * 2008-08-08 This version is a modified version of the original IBM code, but + * the filename and namespace used has been altered along with some + * calling convention changes. As such, it can be used as a drop- + * in replacement for getopt() even on UNIX or Linux systems that + * have their own getopt() implementations in libc without naming + * collisions. This means it can be used portably on any OS with + * a conforming C compiler. It does *not* attempt to implement the + * more long-winded getopt_long() interface. Naming of APIs, + * headers and the optarg/optind externs have been prefixed with + * 'p' to accomplish this. Examples: pgetopt(), poptarg, poptind, + * pgetopt.c, pgetopt.h. Also added some comments to clarify usage + * for the popterr extern. + * Note: This interface keeps external state (to match original + * calling conventions). As such, it is not thread safe, + * and should be called in only one thread (use from main() + * before additional threads are started). As the command + * line should never change, this should not be an issue. + * + */ + +/* Original IBM "AS IS" license follows */ + +/***************************************************************************** + * + * MODULE NAME : GETOPT.H + * + * COPYRIGHTS: + * This module contains code made available by IBM + * Corporation on an AS IS basis. Any one receiving the + * module is considered to be licensed under IBM copyrights + * to use the IBM-provided source code in any way he or she + * deems fit, including copying it, compiling it, modifying + * it, and redistributing it, with or without + * modifications. No license under any IBM patents or + * patent applications is to be implied from this copyright + * license. + * + * A user of the module should understand that IBM cannot + * provide technical support for the module and will not be + * responsible for any consequences of use of the program. + * + * Any notices, including this one, are not to be removed + * from the module without the prior written consent of + * IBM. + * + * AUTHOR: Original author: + * G. R. Blair (BOBBLAIR at AUSVM1) + * Internet: bobblair@bobblair.austin.ibm.com + * + * Extensively revised by: + * John Q. Walker II, Ph.D. (JOHHQ at RALVM6) + * Internet: johnq@ralvm6.vnet.ibm.com + * + *****************************************************************************/ + +#ifndef H_PGETOPT +#define H_PGETOPT 1 + +extern char * poptarg; /* carries the optional argument when a command line + * arg is specified with a ':' after it in the optstring + * and is usually handled by the caller in a switch() + * block. */ +extern int poptind; /* The caller should not need to adjust this normally */ +extern int popterr; /* The pgetopt() function returns a question mark (?) + * when it encounters an option character not included in + * optstring. This error message can be disabled by + * setting popterr to zero. Otherwise, it returns the + * option character that was detected. */ +extern int poptopt; /* actual option character */ + +int pgetopt(int argc, char *argv[], char *optstring); + +/* Example code by PlexFX to demonstrate calling of and parsing optional extra + * args. This is a sample code fragment, untested, minimal or non-existent + * error handling, and some headers variable declarations are omitted. + */ + +#if 0 /* remove, for example purposes only */ + +/* Note the ':' shown below in the pattern string, to specify additional arg */ +char opt_pattern[] = "s:V?"; + +while ((c = pgetopt(argc, argv, opt_pattern)) != -1) +{ + switch(c) + { + case 's': /* specify a /s option with a numeric size parameter + * which is provided in poptarg, a char * + * Example: $ someprogram /s 100 + */ + + some_size = atoi(poptarg); /* should use strtol() in new code */ + break; + case 'V': /* specify a /V version option, with no parameter */ + puts("someprogram: Version 1.0"); + break; + case '?': /* explicit allows of -? or /? */ + default: /* and give usage any time invalid arguments are given */ + PrintUsage(); /* call some function to show usage */ + break; + } +} +#endif /* 0 */ + +#endif /* ! H_GETOPT */ + diff --git a/prep.cmd b/prep.cmd deleted file mode 100755 index 4dc7cb9..0000000 --- a/prep.cmd +++ /dev/null @@ -1,19 +0,0 @@ -@echo off -SET VSVER=10.0 - -IF DEFINED %PROGRAMFILES(X86)% ( - GOTO amd64 -) ELSE ( - GOTO x86 -) - -:amd64 -SET PROGPATH=%PROGRAMFILES(X86)% -GOTO Common - -:x86 -SET PROGPATH=%PROGRAMFILES% -GOTO Common - -:Common -CALL "%PROGPATH%\Microsoft Visual Studio %VSVER%\VC\vcvarsall.bat" x86 diff --git a/range.c b/range.c new file mode 100644 index 0000000..1bf52dd --- /dev/null +++ b/range.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "range.h" + +static LIST_HEAD(Records); + +#define MAX_NAME_LENGTH 256 + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + +// Tests if a newly discovered record checksum location is in an already +// checksummed data. +// This means we found a checksum that, if corrected, will cause a previously +// calculated checksum to be wrong! +static int test_for_data_overlap(const struct ReportRecord *rec, struct list_head *records) +{ + int ret=0; + const struct Range *csum = &rec->checksum; + struct ReportRecordList *rrl; + list_for_each_entry(rrl, records, list) { + struct ReportRecord *rr = &rrl->rr; + const struct RangeList *rl; + if (strncmp(rec->name, rr->name, MAX_NAME_LENGTH)) { + list_for_each_entry(rl, &rr->data.list, list) { + const struct Range *data = &rl->r; + if (MAX(csum->start, data->start)<=MIN(csum->end, data->end)) { + sbprintf(&rr->msg, "%d-%s checksum is in %d-%s data (recheck required): (0x%08x-0x%08x) overlaps with (0x%08x-0x%08x): %s\n", + rec->index, rec->name, rr->index, rr->name, + csum->start, csum->end, + data->start, data->end, + rec->index > rr->index?"ERROR":"OK"); + rr->dep_errs ++; + ret ++; + } + } + } + } + return ret; +} + +// Tests if new data range is in an already calculated checksum +// This is expected. +static int test_for_csum_overlap(struct ReportRecord *rec, struct list_head *records, const struct Range *data) +{ + int ret=0; + struct ReportRecordList *rrl; + list_for_each_entry(rrl, records, list) { + struct ReportRecord *rr = &rrl->rr; + if (strncmp(rec->name, rr->name, MAX_NAME_LENGTH)) { + const struct Range *csum = &rr->checksum; + if (MAX(csum->start, data->start)<=MIN(csum->end, data->end)) { + sbprintf(&rec->msg, "%d-%s checksum is in %d-%s data: (0x%08x-0x%08x) overlaps with (0x%08x-0x%08x): %s\n", + rr->index, rr->name, rec->index, rec->name, + csum->start, csum->end, + data->start, data->end, + rr->index > rec->index?"ERROR":"OK"); + ret ++; + // exit(-1); + } + } + } + return ret; +} + +#if _WIN32 +static inline char *strndup( const char *s1, size_t n) +{ + char *copy= (char*)malloc( n+1 ); + memcpy( copy, s1, n ); + copy[n] = 0; + return copy; +}; +#endif + +struct ReportRecord *CreateRecord(const char *name, uint32_t start, int len) +{ + struct ReportRecordList *rrl = calloc(1, sizeof(struct ReportRecordList)); + struct ReportRecord *rr = &rrl->rr; + //fprintf(stderr,"******* CREATE %s *******\n", name); + rr->name = strndup(name, MAX_NAME_LENGTH); + INIT_LIST_HEAD(&rr->data.list); + rr->checksum.start = start; + rr->checksum.end = start+len-1; + + if (!list_empty(&Records)) { + struct ReportRecordList *prev = + list_entry(Records.prev, struct ReportRecordList, list); + rr->index = prev->rr.index+1; + } else { + rr->index = 1; + } + + + // check if this new checksum is in existing data ranges + test_for_data_overlap(rr, &Records); + list_add_tail(&rrl->list, &Records); + return rr; +} + +void PrintRecord(FILE *fh, struct ReportRecord *rr) +{ + struct RangeList *rl; + + if (!fh) return; + + fprintf(fh, "0x%08x-0x%08x %s CSUM\n", rr->checksum.start, rr->checksum.end, rr->name); + if(rr->msg.pbuf) fprintf(fh, "%s", rr->msg.pbuf); + list_for_each_entry(rl, &rr->data.list, list) { + fprintf(fh, " 0x%08x-0x%08x\n", rl->r.start, rl->r.end); + } + return; +} + +void AddRange(struct ReportRecord *rr, struct Range *r) +{ + struct RangeList *rl = calloc(1, sizeof(struct RangeList)); + rl->r = *r; /* memcpy */ + + // check if this new data range is in existing checksum ranges + test_for_csum_overlap(rr, &Records, &rl->r); + + list_add_tail(&rl->list, &rr->data.list); +} + +void AddRangeStartEnd(struct ReportRecord *rr, uint32_t start, uint32_t end) +{ + struct RangeList *rl = calloc(1, sizeof(struct RangeList)); + rl->r.start = start; + rl->r.end = end; + + // check if this new data range is in existing checksum ranges + test_for_csum_overlap(rr, &Records, &rl->r); + + list_add_tail(&rl->list, &rr->data.list); +} + +void AddRangeStartLength(struct ReportRecord *rr, uint32_t start, int len) +{ + struct RangeList *rl = calloc(1, sizeof(struct RangeList)); + rl->r.start = start; + rl->r.end = start+len-1; + + // check if this new data range is in existing checksum ranges + test_for_csum_overlap(rr, &Records, &rl->r); + + list_add_tail(&rl->list, &rr->data.list); +} + +static void FreeRecord(struct ReportRecordList *rrl) +{ + struct RangeList *rl, *tmp; + list_for_each_entry_safe(rl, tmp, &rrl->rr.data.list, list) { + //struct RangeList *rl = list_entry(e, struct RangeList, list); + list_del(&rl->list); + free(rl); + } + struct ReportRecord *rr = &rrl->rr; + if (rr->name) free(rr->name); + if (rr->msg.pbuf) free(rr->msg.pbuf); + free(rrl); +} + +void PrintAllRecords(FILE *fh) +{ + struct ReportRecordList *rrl; + list_for_each_entry(rrl, &Records, list) { + PrintRecord(fh, &rrl->rr); + } +} + +void FreeAllRecords(void) +{ + struct ReportRecordList *rrl, *tmp; + list_for_each_entry_safe(rrl, tmp, &Records, list) { + list_del(&rrl->list); + FreeRecord(rrl); + } +} + +int ProcessRecordDeps(void) +{ + int errs=0; + struct ReportRecordList *rrl; + list_for_each_entry(rrl, &Records, list) { + struct ReportRecord *rr = &rrl->rr; + if (rr->dep_errs) { + if (rr->callback) { + errs += rr->callback(rr->cb_data, rr); + } else { + printf("%s: no callback for recheck\n", rr->name); + errs++; + } + printf("*** WARNING! %s\n", rr->msg.pbuf); + } + } + return errs; +} + +// vim:ts=4:sw=4:noexpandtab diff --git a/range.h b/range.h new file mode 100644 index 0000000..255100a --- /dev/null +++ b/range.h @@ -0,0 +1,48 @@ +#ifndef _RANGE_H +#define _RANGE_H + +#include +#include + +#include "str.h" +#include "list.h" + +struct Range { + uint32_t start; + uint32_t end; +}; + +struct RangeList { + struct list_head list; /* MSVC doesn't have typeof, so list must always be first */ + + struct Range r; +}; + +struct ReportRecord { + int index; + char *name; /* name of this region */ + struct RangeList data; /* data ranges that it spans */ + struct Range checksum; /* range of checksum data */ + struct strbuf msg; /* dependency messages */ + int dep_errs; /* number of other checksums found later that are in my data */ + + int (*callback)(void *, struct ReportRecord *); + void *cb_data; /* pointer passed to callback */ +}; + +struct ReportRecordList { + struct list_head list; /* MSVC doesn't have typeof, so list must always + be first */ + struct ReportRecord rr; +}; + +extern struct ReportRecord *CreateRecord(const char *name, uint32_t start, int len); +extern void AddRange(struct ReportRecord *rr, struct Range *r); +extern void AddRangeStartEnd(struct ReportRecord *rr, uint32_t start, uint32_t end); +extern void AddRangeStartLength(struct ReportRecord *rr, uint32_t start, int len); +extern void PrintRecord(FILE *fh, struct ReportRecord *rr); +extern void PrintAllRecords(FILE *fh); +extern void FreeAllRecords(void); +extern int ProcessRecordDeps(void); + +#endif /* ! RANGE_H */ diff --git a/rsa.c b/rsa.c new file mode 100644 index 0000000..a14c237 --- /dev/null +++ b/rsa.c @@ -0,0 +1,316 @@ +/********************************************************************** + * * + * Created by Adam Brockett * + * * + * Copyright (c) 2010 * + * * + * Redistribution and use in source and binary forms, with or without * + * modification is allowed. * + * * + * But if you let me know you're using my code, that would be freaking* + * sweet. * + * * + **********************************************************************/ + +#include +#include +#include +#include + +#include "rsa.h" + +#define MODULUS_SIZE 1024 /* This is the number of bits we want in the modulus */ +#define BLOCK_SIZE (MODULUS_SIZE/8) /* This is the size of a block that gets en/decrypted at once */ +#define BUFFER_SIZE ((MODULUS_SIZE/8) / 2) /* This is the number of bytes in n and p */ + +static void generate_random_p(mpz_t p) +{ + char buf[BUFFER_SIZE]; + int i; + + // Set the bits of tmp randomly + for(i = 0; i < BUFFER_SIZE; i++) + buf[i] = rand() % 0xFF; + // Set the top two bits to 1 to ensure int(tmp) is relatively large + buf[0] |= 0xC0; + // Set the bottom bit to 1 to ensure int(tmp) is odd (better for finding primes) + buf[BUFFER_SIZE - 1] |= 0x01; + // Interpret this char buffer as an int + mpz_import(p, BUFFER_SIZE, 1, sizeof(buf[0]), 0, 0, buf); + // Pick the next prime starting from that random number + mpz_nextprime(p, p); +} + +static void generate_primes(private_key *ku) +{ + mpz_t tmp; + + mpz_init(tmp); + + srand(time(NULL)); + + /* Select p and q */ + /* Start with p */ + generate_random_p(ku->p); + + /* Make sure this is a good choice*/ + /* If p mod e == 1, gcd(phi, e) != 1 */ + mpz_mod(tmp, ku->p, ku->e); + while(!mpz_cmp_ui(tmp, 1)) + { + /* Nope. Choose the next prime */ + mpz_nextprime(ku->p, ku->p); + mpz_mod(tmp, ku->p, ku->e); + } + + /* Now select q, where q!=p */ + do { + generate_random_p(ku->q); + /* Make sure this is a good choice*/ + /* If p mod e == 1, gcd(phi, e) != 1 */ + mpz_mod(tmp, ku->q, ku->e); + while(!mpz_cmp_ui(tmp, 1)) + { + /* Nope. Choose the next prime */ + mpz_nextprime(ku->q, ku->q); + mpz_mod(tmp, ku->q, ku->e); + } + } while(mpz_cmp(ku->p, ku->q) == 0); /* If we have identical primes (unlikely), try again */ + + mpz_clear(tmp); +} + +/* NOTE: Assumes mpz_t's are initted in ku and kp */ +int generate_keys(private_key* ku, public_key* kp) +{ + mpz_t phi; + mpz_t tmp1; + mpz_t tmp2; + + mpz_init(phi); + mpz_init(tmp1); + mpz_init(tmp2); + + /* Insetead of selecting e st. gcd(phi, e) = 1; 1 < e < phi, lets choose e + * first then pick p,q st. gcd(e, p-1) = gcd(e, q-1) = 1 */ + // We'll set e globally. I've seen suggestions to use primes like 3, 17 or + // 65537, as they make coming calculations faster. Lets use 3. + mpz_set_ui(ku->e, 3); + + generate_primes(ku); + + /* Calculate n = p x q */ + mpz_mul(ku->n, ku->p, ku->q); + + /* Compute phi(n) = (p-1)(q-1) */ + mpz_sub_ui(tmp1, ku->p, 1); + mpz_sub_ui(tmp2, ku->q, 1); + mpz_mul(phi, tmp1, tmp2); + + mpz_clear(tmp2); + + /* Calculate d (multiplicative inverse of e mod phi) */ + if(mpz_invert(ku->d, ku->e, phi) == 0) + { + mpz_gcd(tmp1, ku->e, phi); + printf("gcd(e, phi) = [%s]\n", mpz_get_str(NULL, 16, tmp1)); + printf("Invert failed\n"); + mpz_clear(tmp1); + mpz_clear(phi); + return -1; + } + + mpz_clear(tmp1); + mpz_clear(phi); + + /* Set public key */ + mpz_set(kp->e, ku->e); + mpz_set(kp->n, ku->n); + + return 0; +} + +void block_encrypt(mpz_t C, mpz_t M, public_key kp) +{ + /* C = M^e mod n */ + mpz_powm(C, M, kp.e, kp.n); + return; +} + +int rsa_encrypt(char *cipher, const char *message, int length, public_key kp) +{ + /* Its probably overkill, but I implemented PKCS#1v1.5 paging + * Encoded message block is of the form: + * EMB = 00 || 02 || PS || 00 || D + * Where || is concatenation, D is the message, and PS is a string of + * (block_size-|D|-3) non-zero, randomly generated bytes + * |D| must be less than block_size - 11, which means we have at least 8 + * bytes of PS + */ + int block_count = 0; + int prog = length; + char mess_block[BLOCK_SIZE]; + mpz_t m; + mpz_t c; + + mpz_init(m); + mpz_init(c); + + while(prog > 0) + { + int i = 0; + int d_len = (prog >= (BLOCK_SIZE - 11)) ? BLOCK_SIZE - 11 : prog; + int off; + + /* Construct the header */ + mess_block[i++] = 0x00; + mess_block[i++] = 0x02; + while(i < (BLOCK_SIZE - d_len - 1)) + mess_block[i++] = (rand() % (0xFF - 1)) + 1; + mess_block[i++] = 0x00; + + /* Copy in the message */ + memcpy(mess_block + i, message + (length - prog), d_len); + + // Convert bytestream to integer + mpz_import(m, BLOCK_SIZE, 1, sizeof(mess_block[0]), 0, 0, mess_block); + // Perform encryption on that block + block_encrypt(c, m, kp); + + // Calculate cipher write offset to take into account that we want to + // pad with zeros in the front if the number we get back has fewer bits + // than BLOCK_SIZE + off = block_count * BLOCK_SIZE; // Base offset to start of this block + off += (BLOCK_SIZE - (mpz_sizeinbase(c, 2) + 8 - 1)/8); // See manual for mpz_export + + // Pull out bytestream of ciphertext + mpz_export(cipher + off, NULL, 1, sizeof(char), 0, 0, c); + + block_count++; + prog -= d_len; + } + + mpz_clear(m); + mpz_clear(c); + + return block_count * BLOCK_SIZE; +} + +void block_decrypt(mpz_t M, mpz_t C, private_key ku) +{ + mpz_powm(M, C, ku.d, ku.n); + return; +} + +int rsa_decrypt(char* message, const char* cipher, int length, private_key ku) +{ + int msg_idx = 0; + char buf[BLOCK_SIZE]; + int i; + mpz_t c; + mpz_t m; + + mpz_init(c); + mpz_init(m); + memset(buf,0,BLOCK_SIZE); + + for(i = 0; i < (length / BLOCK_SIZE); i++) + { + int off; + int j; + + // Pull block into mpz_t + mpz_import(c, BLOCK_SIZE, 1, sizeof(char), 0, 0, cipher + i * BLOCK_SIZE); + // Decrypt block + block_decrypt(m, c, ku); + + // Calculate message write offset to take into account that we want to + // pad with zeros in the front if the number we get back has fewer bits + // than BLOCK_SIZE + off = (BLOCK_SIZE - (mpz_sizeinbase(m, 2) + 8 - 1)/8); // See manual for mpz_export + // Convert back to bitstream + mpz_export(buf + off, NULL, 1, sizeof(char), 0, 0, m); + + // Now we just need to lop off top padding before memcpy-ing to message + // We know the first 2 bytes are 0x00 and 0x02, so manually skip those + // After that, increment forward till we see a zero byte + for(j = 2; ((buf[j] != 0) && (j < BLOCK_SIZE)); j++); + j++; // Skip the 00 byte + + /* Copy over the message part of the plaintext to the message return var */ + memcpy(message + msg_idx, buf + j, BLOCK_SIZE - j); + + msg_idx += BLOCK_SIZE - j; + } + + mpz_clear(c); + mpz_clear(m); + + return msg_idx; +} + +#ifdef TEST +int main() +{ + int i; + mpz_t M; + mpz_t C; + mpz_t DC; + + private_key ku; + public_key kp; + + char buf[BLOCK_SIZE]; + + mpz_init(M); + mpz_init(C); + mpz_init(DC); + + // Initialize public key + mpz_init(kp.n); + mpz_init(kp.e); + + // Initialize private key + mpz_init(ku.n); + mpz_init(ku.e); + mpz_init(ku.d); + mpz_init(ku.p); + mpz_init(ku.q); + + generate_keys(&ku, &kp); + printf("---------------Private Key-----------------"); + printf("kp.n is [%s]\n", mpz_get_str(NULL, 16, kp.n)); + printf("kp.e is [%s]\n", mpz_get_str(NULL, 16, kp.e)); + printf("---------------Public Key------------------"); + printf("ku.n is [%s]\n", mpz_get_str(NULL, 16, ku.n)); + printf("ku.e is [%s]\n", mpz_get_str(NULL, 16, ku.e)); + printf("ku.d is [%s]\n", mpz_get_str(NULL, 16, ku.d)); + printf("ku.p is [%s]\n", mpz_get_str(NULL, 16, ku.p)); + printf("ku.q is [%s]\n", mpz_get_str(NULL, 16, ku.q)); + + for(i = 0; i < BLOCK_SIZE; i++) + buf[i] = rand() % 0xFF; + + mpz_import(M, (BLOCK_SIZE), 1, sizeof(buf[0]), 0, 0, buf); + printf("original is [%s]\n", mpz_get_str(NULL, 16, M)); + block_encrypt(C, M, kp); + printf("encrypted is [%s]\n", mpz_get_str(NULL, 16, C)); + block_decrypt(DC, C, ku); + printf("decrypted is [%s]\n", mpz_get_str(NULL, 16, DC)); + + mpz_clear(M); + mpz_clear(C); + mpz_clear(DC); + + mpz_clear(kp.n); + mpz_clear(kp.e); + + mpz_clear(ku.n); + mpz_clear(ku.e); + mpz_clear(ku.d); + mpz_clear(ku.p); + mpz_clear(ku.q); + + return 0; +} +#endif diff --git a/rsa.h b/rsa.h new file mode 100644 index 0000000..21c0eb5 --- /dev/null +++ b/rsa.h @@ -0,0 +1,24 @@ +#ifdef _WIN32 +#include "mpir/gmp.h" +#else +#include +#endif + +typedef struct { + mpz_t n; /* Modulus */ + mpz_t e; /* Public Exponent */ +} public_key; + +typedef struct { + mpz_t n; /* Modulus */ + mpz_t e; /* Public Exponent */ + mpz_t d; /* Private Exponent */ + mpz_t p; /* Starting prime p */ + mpz_t q; /* Starting prime q */ +} private_key; + +extern int generate_keys(private_key* ku, public_key* kp); +extern void block_encrypt(mpz_t C, mpz_t M, public_key kp); +extern int rsa_encrypt(char* cipher, const char *message, int length, public_key kp); +extern void block_decrypt(mpz_t M, mpz_t C, private_key ku); +extern int rsa_decrypt(char* message, const char* cipher, int length, private_key ku); diff --git a/sample.ini b/sample.ini new file mode 100644 index 0000000..30e0f19 --- /dev/null +++ b/sample.ini @@ -0,0 +1,21 @@ +[ignition] +rom_firmware_start=0x800000 # defaults to 0x800000 +rom_checksum_block_start0=0x0 +rom_checksum_block_start=0x0 +rom_checksum_block_len=0x10 # defaults to 0x10 +rom_checksum_offset=0x0 +rom_checksum_final=0x0 +rom_crc0_start=0x0 +rom_crc0_end=0x0 +rom_crc1_start=0x0 +rom_crc1_end=0x0 +rom_crc1=0x0 +rom_crc2_start=0x0 +rom_crc2_end=0x0 +rom_crc2=0x0 +rom_crc3_start=0x0 +rom_crc3_end=0x0 +rom_crc3=0x0 +rom_crc4_start=0x0 +rom_crc4_end=0x0 +rom_crc4=0x0 diff --git a/save_file.c b/save_file.c deleted file mode 100644 index f528fc4..0000000 --- a/save_file.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Simple write file from memory - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -*/ -#include "save_file.h" - -/* load a file into memory and return buffer */ -int save_file(char *filename, unsigned char *filebuf, size_t filelen) -{ - FILE *fp; - size_t bytesWritten; - - /* open file */ - printf("þ Opening '%s' file for writing\n",filename); - if ((fp = (FILE *)fopen(filename, "wb")) == NULL){ printf("\nCan't open file \"%s\".", filename); return(-1); } - - /* load file into buffer */ - printf("þ Writing to file\n"); - bytesWritten = fwrite((void *)filebuf, (size_t)1, (size_t)filelen, fp); - - /* validate it all loaded correctly */ - printf("þ Validating size correct %d=%d\n",(int)bytesWritten,(int)filelen); - if(bytesWritten != filelen) { printf("\nfailed to write buffer\n"); fclose(fp); return(-2); } - - /* close the file */ - printf("þ All OK, closing file\n\n"); - fclose(fp); - - return(0); -} diff --git a/save_file.h b/save_file.h deleted file mode 100644 index 2f03533..0000000 --- a/save_file.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Simple write file from memory - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -*/ -#ifndef _SAVE_FILE_H_ -#define _SAVE_FILE_H_ - -#include -#include -#include - -/* save a file from memory */ -int save_file(char *filename, unsigned char *filebuf, size_t filelen); - -#endif diff --git a/str.c b/str.c new file mode 100644 index 0000000..5acb109 --- /dev/null +++ b/str.c @@ -0,0 +1,385 @@ +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#endif + +#include "str.h" + +#define ASSERT assert +#define MAC_DELIMITER(c) ( c == ':' || c == '-' ) + +#ifdef _WIN32 +#ifndef va_copy +#define va_copy(d,s) ((d) = (s)) +#endif +#endif + +#if 0 +/** Strip all cr/lf from end of string. Modifies string in place */ +int chomp_crlf(char *str, int len) +{ + if (len) { + while (str[len-1] == '\n' || str[len-1] == '\r') { + str[--len] = '\0'; + if (!len) + break; + } + } + return len; +} +#endif + +/** chomp whitespace from the end of the string */ +int chomp(char *str) +{ + int len=strlen(str); + while ((len > 0) && isspace((unsigned char)str[len-1])) + str[--len] = '\0'; + return len; +} + +int chompn(char *str, int len) +{ + len=strnlen(str,len); + while ((len > 0) && isspace((unsigned char)str[len-1])) + str[--len] = '\0'; + return len; +} + +#if 0 /* unused */ +char *sbchomp(struct strbuf *buf) +{ + if(!buf) return NULL; + buf->offset=chompn(buf->pbuf,buf->offset); + return buf->pbuf; +} +#endif + +/** Converts ascii MAC address with any delimiters hex values without delimiters. + return 0 = success + 1 = error + */ +int atomac(unsigned char * mac, char * buf) +{ + int len=0; + + atohex(mac, buf, &len); + + if (len != 6) + return 1; + return 0; +} + +int atomac_no_delim(unsigned char * mac, char * buf) +{ + int len=0; + + atohex_no_delim(mac, buf, &len); + + if (len != 6) + return 1; + return 0; +} + +/* ensure that strbuf has room enough for at least n bytes */ +void sbensure(struct strbuf *sb, int n) +{ + size_t len; + char *buf = NULL; + + ASSERT(sb != NULL); + len = sb->len; + if ((sb->pbuf != NULL) && ((len - sb->offset) >= n)) + return; + + /* Grow buffer exponentially, rather than per addendum */ + if (len == 0) len = 100; + while ((len - sb->offset) < n) + len *= 2; + + buf = realloc(sb->pbuf, len); + // ASSERT_INFO((buf != NULL), "%zu", len); +#ifdef _MALLOC_H + { + size_t usable = malloc_usable_size(buf); + /* Take advantage of full usable allocation */ + sb->len = (usable > len) ? usable : len; + } +#else + sb->len = len; +#endif + sb->pbuf = buf; +} + +/** Printf into an automatically extended string buffer */ +int vsbprintf(struct strbuf *param, const char *fmt, va_list ap) +{ + int ret; + char *buf; + + if (!param) return 0; + + buf = param->pbuf; + + if(!buf) { + if (param->len == 0) + param->len = 100; + buf = malloc(param->len); + // ASSERT_INFO((buf != NULL), "%zu", param->len); +#ifdef _MALLOC_H + { + /* Take advantage of full usable allocation */ + size_t usable = malloc_usable_size(buf); + if (param->len < usable) + param->len = usable; + } +#endif + } + + while(1) { + int rem = param->len - param->offset; + va_list cp; + va_copy(cp, ap); + ret = vsnprintf(buf + param->offset, rem, fmt, cp); + va_end(cp); + if(ret == -1) buf = realloc(buf, param->len *= 2); + else if(ret >= rem) buf = realloc(buf, param->len += ret); + else break; + //ASSERT_INFO((buf != NULL), "%zu", param->len); +#ifdef _MALLOC_H + { + /* Take advantage of full usable allocation */ + size_t usable = malloc_usable_size(buf); + if (param->len < usable) + param->len = usable; + } +#endif + } + param->offset += ret; + param->pbuf = buf; + return ret; +} + +int sbprintf(struct strbuf *param, const char *fmt, ...) +{ + va_list ap; + int ret; + va_start(ap, fmt); + ret=vsbprintf(param, fmt, ap); + va_end(ap); + return ret; +} + +void sbputs(struct strbuf *sb, const char *s) +{ + int len = strlen(s); + ASSERT(sb != NULL); + sbensure(sb, len + 1); + memcpy(sb->pbuf + sb->offset, s, len + 1); + sb->offset += len; +} + +char *sbfill(struct strbuf *sb, char fill, int width) +{ + char buf[]={fill,'\0'}; + int off=sb->offset; + if(width) { + sbprintf(sb, "%*s", width, buf); + memset(sb->pbuf+off, fill, width); + } + return sb->pbuf; +} + +/** Run isdigit() across this str. */ +static int str_is_xdigit(char *str, int len) +{ + int i; + + for(i = 0; i < len; i++) { + if (!isxdigit((unsigned char)str[i])) + return 0; + } + return 1; +} + +// Converts 2-byte/value ascii hex string with any delimiter into hex values +// Examples: 11.22.33.44 , 0a-b9-c2 , aa1bb2cc3 (delim=1,2,3) +// +// return 0 = success, 1 = error +// +int atohex(unsigned char * data, char * buf, int *digits) +{ + int i,j,len; + + len = strlen(buf); + if ((len-2) % 3) + return 1; + + for (i=0,j=0; i 0) + if (!isspace((unsigned char)(*buf++))) + return 0; + return 1; +} + +/** + * convert an ascii string of (up to a) 64-bit number (max 20 chars) to a comma-separated string + * 'space' is buffer space for adding commas; if not enough, do nothing + * return # of commas added +**/ +int comma_separated(char *buf, int space) +{ + int i,j; + int len=strlen(buf); + int commas=0; + char *dptr,*sptr; + + if (len>20) // 20 chars = max for 64-bit decimal number + return 0; + + for (i=0,j=0; ipbuf) { + free(sb->pbuf); + sb->pbuf = NULL; + sb->offset = sb->len = 0; + } +} + +#if _MSC_VER +static char *strtok_r(char *str, const char *delim, char **saveptr) +{ + return strtok(str, delim); +} +#endif + +int str_split(char *buf, char *argv[], int maxargc, const char *split) +{ + int argc; + char *lasts=NULL; + + ASSERT(buf); + + for(argc=0,argv[0]=buf;argc +#include /* most callers want the prototype for free() too */ +#include + +/* GCC have printf type attribute check. */ +#ifdef __GNUC__ +#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) +#else +#define PRINTF_ATTRIBUTE(a,b) +#endif /* __GNUC__ */ + +#ifndef STR +# define X__STR(x) # x +# define STR(x) X__STR(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** expanding string buffer for \ref sbprintf */ +struct strbuf { + char *pbuf; + size_t offset; + size_t len; +}; + +int atomac(unsigned char * mac, char * buf); +int atomac_no_delim(unsigned char * mac, char * buf); +int atohex(unsigned char * mac, char * buf, int *digits); +int atohex_no_delim(unsigned char * mac, char * buf, int *digits); + +int chomp(char *str); +int chompn(char *str, int len); +int str_is_digit(char *str, int len); +void str_clean(char *str, int len); +int str_split(char *str, char *argv[], int maxargc, const char *split); +int iszero(const void *buf, int len); +int isempty(const char *buf, int len); +int comma_separated(char *buf, int space); + +int sbprintf(struct strbuf *param, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); +int vsbprintf(struct strbuf *param, const char *fmt, va_list ap); +void sprint_spaces(char *buf, int nspaces); +void sbensure(struct strbuf *sb, int len); +char *sbfill(struct strbuf *sb, char fill, int width); +void sbfree(struct strbuf *sb); + +/* init sb with malloc'ed string. */ +#ifdef _WIN32 +#define __INLINE __inline +#else +#define __INLINE static inline +#endif + +__INLINE void strbuf_from_str(struct strbuf *sb, char *str) +{ + sb->pbuf = str; + sb->len = sb->offset = strlen(str); +} + +/* safety string copy */ +__INLINE int snputs(char *dest, const char *src, size_t n) +{ + if (n<=0) return 0; + + strncpy(dest, src, n); + dest[n-1]='\0'; + + return strnlen(dest, n); +} + +void sbputs(struct strbuf *sb, const char *s); + +#ifdef __cplusplus +} +#endif + +#endif /* STR_H */ diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..f8a37ac --- /dev/null +++ b/test.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +rm -f err.log +trap "rm -rf err.log" EXIT +for i in bins/*.bin; do + ./me7sum -r $i.txt $i | grep -E '(ABORT|WARNING)' >> err.log + grep ERROR $i.txt >> err.log +done + +cat err.log +[ ! -s err.log ] diff --git a/utils.c b/utils.c index 3c02ada..ad2aded 100644 --- a/utils.c +++ b/utils.c @@ -1,11 +1,36 @@ +/* Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#include +#include + #include "utils.h" -int iload_file(struct ImageHandle *ih, const char *fname, int rw) +int iload_file(struct ImageHandle *ih, const char *fname, int rw, struct strbuf *buf) { // init image handle structure to zero's memset(ih, 0, sizeof(*ih)); // load file into memory - if(((ih->d.p)= (void *)load_file((char *)fname,&ih->len)) == 0) return -1; + if(((ih->d.p)= (void *)load_file(fname,&ih->len,buf)) == 0) return -1; + snprintf(ih->filename, sizeof(ih->filename), "%s", fname); return 0; } @@ -15,3 +40,125 @@ int ifree_file(struct ImageHandle *ih) memset(ih, 0, sizeof(*ih)); return 0; } + +/* load a file into memory and return buffer */ +uint8_t *load_file(const char *filename, size_t *filelen, struct strbuf *buf) +{ + FILE *fp; + uint8_t *data; + size_t size,bytesRead; + + /* open file */ + sbprintf(buf, "þ Opening '%s'\n",filename); + if ((fp = (FILE *)fopen(filename, "rb")) == NULL) { sbprintf(buf, "\nCan't open '%s'.\n", filename); return(0); } + + /* get file length */ + sbprintf(buf, "þ Getting length of '%s'\n",filename); + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + if(size <= 0) { sbprintf(buf, "Error: Problem with seeking filesize\n"); fclose(fp); return(0); } + + *filelen = size; /* return size of file to caller */ + + /* alloc buffer for file */ + sbprintf(buf, "þ Allocating buffer of %d bytes\n",(int)size); + data = (uint8_t *)malloc(size); + if(data == 0) { sbprintf(buf, "\nfailed to allocate memory to load module\n"); fclose(fp); return 0; } + + /* load file into buffer */ + sbprintf(buf, "þ Reading file to buffer\n"); + bytesRead = fread(data, 1, size, fp); + + /* validate it all loaded correctly */ + sbprintf(buf, "þ Validating size correct %d=%d\n",(int)bytesRead,(int)size); + if(bytesRead != size) { sbprintf(buf, "\nfailed to load module into buffer\n"); free(data); fclose(fp); return 0; } + + /* close the file */ + sbprintf(buf, "þ Closing file\n"); + fclose(fp); + return(data); +} + +/* load a file into memory and return buffer */ +int save_file(const char *filename, const uint8_t *filebuf, size_t filelen, struct strbuf *buf) +{ + FILE *fp; + size_t bytesWritten; + + /* open file */ + sbprintf(buf, "þ Opening '%s' file for writing\n",filename); + if ((fp = (FILE *)fopen(filename, "wb")) == NULL){ sbprintf(buf, "\nCan't open file \"%s\".", filename); return(-1); } + + /* load file into buffer */ + sbprintf(buf, "þ Writing to file\n"); + bytesWritten = fwrite((void *)filebuf, (size_t)1, (size_t)filelen, fp); + + /* validate it all loaded correctly */ + sbprintf(buf, "þ Validating size correct %d=%d\n",(int)bytesWritten,(int)filelen); + if(bytesWritten != filelen) { sbprintf(buf, "\nfailed to write buffer\n"); fclose(fp); return(-2); } + + /* close the file */ + sbprintf(buf, "þ All OK, closing file\n"); + fclose(fp); + + return(0); +} + +static int memcmp_mask(const void *ptr1, const void *ptr2, const void *mask, size_t len) +{ + const uint8_t *p1 = (const uint8_t*)ptr1; + const uint8_t *p2 = (const uint8_t*)ptr2; + const uint8_t *m = (const uint8_t*)mask; + + while(len--) + { + int diff = m?(*p2 & *m)-(*p1 & *m):*p2-*p1; + if (diff) return diff>0?1:-1; + p1++; + p2++; + if (m) m++; + } + return 0; +} + +/* returns -1 on failure, start if found */ +int search_image(const struct ImageHandle *ih, size_t start, const void *needle, const void *mask, int len, int align) +{ + if (start<0) return -1; + + for (;start+lenlen;start+=align) + { + if(memcmp_mask(ih->d.u8+start, needle, mask, len)==0) + { + // printf("got one at 0x%x\n", start); + return start; + } + } + return -1; +} + +void hexdump(const uint8_t *buf, int len, const char *end) +{ + int i=len; + while(i--) + printf("%02x%s", *buf++, ((i&0xf)==0 && len>32)?"\n":i?" ":""); + printf("%s", end); +} + +#if 0 +#ifdef _WIN32 +int snprintf(char *str, size_t size, const char *format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = _vsnprintf(str, size, format, ap); + va_end(ap); + str[size-1]='\0'; + + return count; +} +#endif +#endif diff --git a/utils.h b/utils.h index b182f8a..817ed66 100644 --- a/utils.h +++ b/utils.h @@ -1,15 +1,48 @@ +/* + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + #ifndef _UTILS_H #define _UTILS_H #include #include +#include + #ifdef _WIN32 -#else -#include +#include +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif #endif -#include "load_file.h" -#include "save_file.h" +#include "str.h" + +enum Padding { + PADDING_NONE=0, + PADDING_00, + PADDING_FF, + PADDING_TRY_512K_CRC, + PADDING_DOUBLED +}; struct ImageHandle { union { @@ -20,8 +53,23 @@ struct ImageHandle { void *p; } d; size_t len; + enum Padding pad; + int bootrom_whitelist; + char filename[PATH_MAX]; }; +/* + * If htole16() is missing, let's assume that other *le*() functions + * are also missing. + * + * OpenBSD - htole16 & 32 exist, but not le16toh etc + */ +#if defined(__OpenBSD__) +#define le16toh(x) htole16(x) +#define le32toh(x) htole32(x) +#endif + +#if !defined(htole16) #if __BYTE_ORDER == __LITTLE_ENDIAN #define le32toh(x) (x) #define le16toh(x) (x) @@ -33,6 +81,7 @@ struct ImageHandle { #define le32toh(x) __bswap_32(x) #define htole16(x) __bswap_16(x) #endif +#endif // they're the same. #define memcpy_to_le32 memcpy_from_le32 @@ -48,7 +97,13 @@ struct ImageHandle { } #endif -int iload_file(struct ImageHandle *ih, const char *fname, int rw); +int iload_file(struct ImageHandle *ih, const char *fname, int rw, struct strbuf *buf); int ifree_file(struct ImageHandle *ih); +int save_file(const char *filename, const uint8_t *filebuf, size_t filelen, struct strbuf *buf); +uint8_t *load_file(const char *filename, size_t *filelen, struct strbuf *buf); + +int search_image(const struct ImageHandle *ih, size_t start, const void *needle, const void *mask, int len, int align); + +void hexdump(const uint8_t *buf, int len, const char *end); #endif diff --git a/vars.mk b/vars.mk index 84a3733..2228848 100644 --- a/vars.mk +++ b/vars.mk @@ -1,14 +1,35 @@ -RM =rm -f -CC =gcc -AR =ar rcs -ECHO =@echo -CFLAGS =-Wall -O3 -Werror - -UNAME := $(shell uname -s) -ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) -# CFLAGS += -D_WIN32_ -EXE_EXT := .exe +RM = rm -f +AR = ar rcs +ECHO = @echo + +#CASAN = -fsanitize=address -fsanitize=undefined -fno-sanitize=alignment +#LASAN = -lasan -lubsan + +CFLAGS += -Wall -O2 -g -Werror -MMD $(CASAN) $(CDEFS) + +CDEFS += -D__GIT_VERSION=\"$(GIT_VERSION)\" + +GIT_VERSION = $(shell sh -c 'git describe --tags --abbrev=4 --dirty --always') +SYS := $(shell gcc -dumpmachine) +#SYS := i686-w64-mingw32 + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) +CC = gcc +LD = gcc +LDFLAGS += -L /opt/homebrew/lib -Linifile $(LASAN) $(GMP_LINK) -lgmp -Wl,-dynamic +CFLAGS += -I /opt/homebrew/include else +CC = $(SYS)-gcc +LD = $(SYS)-gcc +LDFLAGS += -Linifile $(LASAN) $(GMP_LINK) -lgmp -Wl,-Bdynamic endif -SRC =$(notdir $(foreach dir, ., $(wildcard $(dir)/*.c))) +SRC = $(notdir $(foreach dir, ., $(wildcard $(dir)/*.c))) + +ifneq (, $(findstring mingw, $(SYS))) +GMP_LINK = -Wl,-Bstatic +EXE_EXT = .exe +else ifneq (, $(findstring cygwin, $(SYS))) +EXE_EXT = -cyg.exe +endif