The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .github
    ├── FUNDING.yml
    └── workflows
    │   └── build.yml
├── .gitignore
├── COPYING
├── Makefile.am
├── NEWS
├── README.md
├── autogen.sh
├── configure.ac
├── git-version-gen
├── include
    ├── Makefile.am
    └── libirecovery.h
├── m4
    └── as-compiler-flag.m4
├── src
    ├── Makefile.am
    ├── libirecovery-1.0.pc.in
    └── libirecovery.c
├── tools
    ├── Makefile.am
    └── irecovery.c
└── udev
    ├── 39-libirecovery.rules.in
    └── Makefile.am


/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: nikias
2 | patreon: nikias
3 | custom: ["https://www.paypal.me/NikiasBassen"]
4 | 


--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
  1 | name: build
  2 | 
  3 | on:
  4 |   push:
  5 |   schedule:
  6 |     - cron: '0 0 1 * *'
  7 | 
  8 | jobs:
  9 |   build-linux-ubuntu:
 10 |     runs-on: ubuntu-latest
 11 |     steps:
 12 |     - name: install dependencies
 13 |       run: |
 14 |           sudo apt-get update
 15 |           sudo apt-get install libusb-1.0-0-dev
 16 |     - name: prepare environment
 17 |       run: |
 18 |           echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV
 19 |     - name: fetch libplist
 20 |       uses: dawidd6/action-download-artifact@v6
 21 |       with:
 22 |         github_token: ${{secrets.GITHUB_TOKEN}}
 23 |         workflow: build.yml
 24 |         name: libplist-latest_${{env.target_triplet}}
 25 |         repo: libimobiledevice/libplist
 26 |     - name: fetch libimobiledevice-glue
 27 |       uses: dawidd6/action-download-artifact@v6
 28 |       with:
 29 |         github_token: ${{secrets.GITHUB_TOKEN}}
 30 |         workflow: build.yml
 31 |         name: libimobiledevice-glue-latest_${{env.target_triplet}}
 32 |         repo: libimobiledevice/libimobiledevice-glue
 33 |     - name: install external dependencies
 34 |       run: |
 35 |           mkdir extract
 36 |           for I in *.tar; do
 37 |             tar -C extract -xvf $I
 38 |           done
 39 |           sudo cp -r extract/* /
 40 |           sudo ldconfig
 41 |     - uses: actions/checkout@v4
 42 |     - name: autogen
 43 |       run: ./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig LDFLAGS="-Wl,-rpath=/usr/local/lib"
 44 |     - name: make
 45 |       run: make
 46 |     - name: make install
 47 |       run: sudo make install
 48 |     - name: prepare artifact
 49 |       run: |
 50 |           mkdir -p dest
 51 |           DESTDIR=`pwd`/dest make install
 52 |           tar -C dest -cf libirecovery.tar --strip-components 1 .
 53 |     - name: publish artifact
 54 |       uses: actions/upload-artifact@v4
 55 |       with:
 56 |         name: libirecovery-latest_${{env.target_triplet}}
 57 |         path: libirecovery.tar
 58 |   build-macOS:
 59 |     runs-on: macOS-latest
 60 |     steps:
 61 |     - name: install dependencies
 62 |       run: |
 63 |           if test -x "`which port`"; then
 64 |             sudo port install libtool autoconf automake pkgconfig
 65 |           else
 66 |             brew install libtool autoconf automake pkgconfig
 67 |           fi
 68 |       shell: bash
 69 |     - name: fetch libplist
 70 |       uses: dawidd6/action-download-artifact@v6
 71 |       with:
 72 |         github_token: ${{secrets.GITHUB_TOKEN}}
 73 |         workflow: build.yml
 74 |         name: libplist-latest_macOS
 75 |         repo: libimobiledevice/libplist
 76 |     - name: fetch libimobiledevice-glue
 77 |       uses: dawidd6/action-download-artifact@v6
 78 |       with:
 79 |         github_token: ${{secrets.GITHUB_TOKEN}}
 80 |         workflow: build.yml
 81 |         name: libimobiledevice-glue-latest_macOS
 82 |         repo: libimobiledevice/libimobiledevice-glue
 83 |     - name: install external dependencies
 84 |       run: |
 85 |           mkdir extract
 86 |           for I in *.tar; do
 87 |             tar -C extract -xvf $I
 88 |           done
 89 |           sudo cp -r extract/* /
 90 |     - uses: actions/checkout@v4
 91 |     - name: autogen
 92 |       run: |
 93 |           SDKDIR=`xcrun --sdk macosx --show-sdk-path`
 94 |           TESTARCHS="arm64 x86_64"
 95 |           USEARCHS=
 96 |           for ARCH in $TESTARCHS; do
 97 |             if echo "int main(int argc, char **argv) { return 0; }" |clang -arch $ARCH -o /dev/null -isysroot $SDKDIR -x c - 2>/dev/null; then
 98 |               USEARCHS="$USEARCHS -arch $ARCH"
 99 |             fi
100 |           done
101 |           export CFLAGS="$USEARCHS -isysroot $SDKDIR"
102 |           echo "Using CFLAGS: $CFLAGS"
103 |           ./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
104 |     - name: make
105 |       run: make
106 |     - name: make install
107 |       run: sudo make install
108 |     - name: prepare artifact
109 |       run: |
110 |           mkdir -p dest
111 |           DESTDIR=`pwd`/dest make install
112 |           tar -C dest -cf libirecovery.tar --strip-components 1 .
113 |     - name: publish artifact
114 |       uses: actions/upload-artifact@v4
115 |       with:
116 |         name: libirecovery-latest_macOS
117 |         path: libirecovery.tar
118 |   build-windows:
119 |     runs-on: windows-latest
120 |     defaults:
121 |       run:
122 |         shell: msys2 {0}
123 |     strategy:
124 |       fail-fast: false
125 |       matrix:
126 |         include: [
127 |           { msystem: MINGW64, arch: x86_64 },
128 |           { msystem: MINGW32, arch: i686   }
129 |         ]
130 |     steps:
131 |     - uses: msys2/setup-msys2@v2
132 |       with:
133 |         msystem: ${{ matrix.msystem }}
134 |         release: false
135 |         update: false
136 |         install: >-
137 |           base-devel
138 |           git
139 |           mingw-w64-${{ matrix.arch }}-gcc
140 |           mingw-w64-${{ matrix.arch }}-pkg-config
141 |           make
142 |           libtool
143 |           autoconf
144 |           automake-wrapper
145 |     - name: prepare environment
146 |       run: |
147 |           dest=`echo ${{ matrix.msystem }} |tr [:upper:] [:lower:]`
148 |           echo "dest=$dest" >> $GITHUB_ENV
149 |           echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV
150 |     - name: fetch libplist
151 |       uses: dawidd6/action-download-artifact@v6
152 |       with:
153 |         github_token: ${{secrets.GITHUB_TOKEN}}
154 |         workflow: build.yml
155 |         name: libplist-latest_${{ matrix.arch }}-${{ env.dest }}
156 |         repo: libimobiledevice/libplist
157 |     - name: fetch libimobiledevice-glue
158 |       uses: dawidd6/action-download-artifact@v6
159 |       with:
160 |         github_token: ${{secrets.GITHUB_TOKEN}}
161 |         workflow: build.yml
162 |         name: libimobiledevice-glue-latest_${{ matrix.arch }}-${{ env.dest }}
163 |         repo: libimobiledevice/libimobiledevice-glue
164 |     - name: install external dependencies
165 |       run: |
166 |           mkdir extract
167 |           for I in *.tar; do
168 |             tar -C extract -xvf $I
169 |           done
170 |           cp -r extract/* /
171 |     - uses: actions/checkout@v4
172 |     - name: autogen
173 |       run: ./autogen.sh CC=gcc CXX=g++
174 |     - name: make
175 |       run: make
176 |     - name: make install
177 |       run: make install
178 |     - name: prepare artifact
179 |       run: |
180 |           mkdir -p dest
181 |           DESTDIR=`pwd`/dest make install
182 |           tar -C dest -cf libirecovery.tar ${{ env.dest }}
183 |     - name: publish artifact
184 |       uses: actions/upload-artifact@v4
185 |       with:
186 |         name: libirecovery-latest_${{ matrix.arch }}-${{ env.dest }}
187 |         path: libirecovery.tar
188 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | *.[oa]
 2 | *~
 3 | *.po
 4 | *.lo
 5 | *.la
 6 | autom4te.cache/*
 7 | *.in
 8 | */.deps/*
 9 | m4/*
10 | *.dll
11 | *.so
12 | *.dylib
13 | *.patch
14 | aclocal.m4
15 | config.h
16 | config.log
17 | config.sub
18 | config.guess
19 | config.status
20 | configure
21 | depcomp
22 | install-sh
23 | compile
24 | main
25 | ltmain.sh
26 | missing
27 | mkinstalldirs
28 | libtool
29 | *Makefile
30 | stamp-h1
31 | src/.libs
32 | *.pc
33 | tools/.libs/*
34 | tools/irecovery
35 | .irecovery
36 | udev/39-libirecovery.rules
37 | .idea
38 | .vscode
39 | .DS_Store
40 | 


--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
  1 |                   GNU LESSER GENERAL PUBLIC LICENSE
  2 |                        Version 2.1, February 1999
  3 | 
  4 |  Copyright (C) 1991, 1999 Free Software Foundation, Inc.
  5 |  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  6 |  Everyone is permitted to copy and distribute verbatim copies
  7 |  of this license document, but changing it is not allowed.
  8 | 
  9 | [This is the first released version of the Lesser GPL.  It also counts
 10 |  as the successor of the GNU Library Public License, version 2, hence
 11 |  the version number 2.1.]
 12 | 
 13 |                             Preamble
 14 | 
 15 |   The licenses for most software are designed to take away your
 16 | freedom to share and change it.  By contrast, the GNU General Public
 17 | Licenses are intended to guarantee your freedom to share and change
 18 | free software--to make sure the software is free for all its users.
 19 | 
 20 |   This license, the Lesser General Public License, applies to some
 21 | specially designated software packages--typically libraries--of the
 22 | Free Software Foundation and other authors who decide to use it.  You
 23 | can use it too, but we suggest you first think carefully about whether
 24 | this license or the ordinary General Public License is the better
 25 | strategy to use in any particular case, based on the explanations below.
 26 | 
 27 |   When we speak of free software, we are referring to freedom of use,
 28 | not price.  Our General Public Licenses are designed to make sure that
 29 | you have the freedom to distribute copies of free software (and charge
 30 | for this service if you wish); that you receive source code or can get
 31 | it if you want it; that you can change the software and use pieces of
 32 | it in new free programs; and that you are informed that you can do
 33 | these things.
 34 | 
 35 |   To protect your rights, we need to make restrictions that forbid
 36 | distributors to deny you these rights or to ask you to surrender these
 37 | rights.  These restrictions translate to certain responsibilities for
 38 | you if you distribute copies of the library or if you modify it.
 39 | 
 40 |   For example, if you distribute copies of the library, whether gratis
 41 | or for a fee, you must give the recipients all the rights that we gave
 42 | you.  You must make sure that they, too, receive or can get the source
 43 | code.  If you link other code with the library, you must provide
 44 | complete object files to the recipients, so that they can relink them
 45 | with the library after making changes to the library and recompiling
 46 | it.  And you must show them these terms so they know their rights.
 47 | 
 48 |   We protect your rights with a two-step method: (1) we copyright the
 49 | library, and (2) we offer you this license, which gives you legal
 50 | permission to copy, distribute and/or modify the library.
 51 | 
 52 |   To protect each distributor, we want to make it very clear that
 53 | there is no warranty for the free library.  Also, if the library is
 54 | modified by someone else and passed on, the recipients should know
 55 | that what they have is not the original version, so that the original
 56 | author's reputation will not be affected by problems that might be
 57 | introduced by others.
 58 | 
 59 |   Finally, software patents pose a constant threat to the existence of
 60 | any free program.  We wish to make sure that a company cannot
 61 | effectively restrict the users of a free program by obtaining a
 62 | restrictive license from a patent holder.  Therefore, we insist that
 63 | any patent license obtained for a version of the library must be
 64 | consistent with the full freedom of use specified in this license.
 65 | 
 66 |   Most GNU software, including some libraries, is covered by the
 67 | ordinary GNU General Public License.  This license, the GNU Lesser
 68 | General Public License, applies to certain designated libraries, and
 69 | is quite different from the ordinary General Public License.  We use
 70 | this license for certain libraries in order to permit linking those
 71 | libraries into non-free programs.
 72 | 
 73 |   When a program is linked with a library, whether statically or using
 74 | a shared library, the combination of the two is legally speaking a
 75 | combined work, a derivative of the original library.  The ordinary
 76 | General Public License therefore permits such linking only if the
 77 | entire combination fits its criteria of freedom.  The Lesser General
 78 | Public License permits more lax criteria for linking other code with
 79 | the library.
 80 | 
 81 |   We call this license the "Lesser" General Public License because it
 82 | does Less to protect the user's freedom than the ordinary General
 83 | Public License.  It also provides other free software developers Less
 84 | of an advantage over competing non-free programs.  These disadvantages
 85 | are the reason we use the ordinary General Public License for many
 86 | libraries.  However, the Lesser license provides advantages in certain
 87 | special circumstances.
 88 | 
 89 |   For example, on rare occasions, there may be a special need to
 90 | encourage the widest possible use of a certain library, so that it becomes
 91 | a de-facto standard.  To achieve this, non-free programs must be
 92 | allowed to use the library.  A more frequent case is that a free
 93 | library does the same job as widely used non-free libraries.  In this
 94 | case, there is little to gain by limiting the free library to free
 95 | software only, so we use the Lesser General Public License.
 96 | 
 97 |   In other cases, permission to use a particular library in non-free
 98 | programs enables a greater number of people to use a large body of
 99 | free software.  For example, permission to use the GNU C Library in
100 | non-free programs enables many more people to use the whole GNU
101 | operating system, as well as its variant, the GNU/Linux operating
102 | system.
103 | 
104 |   Although the Lesser General Public License is Less protective of the
105 | users' freedom, it does ensure that the user of a program that is
106 | linked with the Library has the freedom and the wherewithal to run
107 | that program using a modified version of the Library.
108 | 
109 |   The precise terms and conditions for copying, distribution and
110 | modification follow.  Pay close attention to the difference between a
111 | "work based on the library" and a "work that uses the library".  The
112 | former contains code derived from the library, whereas the latter must
113 | be combined with the library in order to run.
114 | 
115 |                   GNU LESSER GENERAL PUBLIC LICENSE
116 |    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117 | 
118 |   0. This License Agreement applies to any software library or other
119 | program which contains a notice placed by the copyright holder or
120 | other authorized party saying it may be distributed under the terms of
121 | this Lesser General Public License (also called "this License").
122 | Each licensee is addressed as "you".
123 | 
124 |   A "library" means a collection of software functions and/or data
125 | prepared so as to be conveniently linked with application programs
126 | (which use some of those functions and data) to form executables.
127 | 
128 |   The "Library", below, refers to any such software library or work
129 | which has been distributed under these terms.  A "work based on the
130 | Library" means either the Library or any derivative work under
131 | copyright law: that is to say, a work containing the Library or a
132 | portion of it, either verbatim or with modifications and/or translated
133 | straightforwardly into another language.  (Hereinafter, translation is
134 | included without limitation in the term "modification".)
135 | 
136 |   "Source code" for a work means the preferred form of the work for
137 | making modifications to it.  For a library, complete source code means
138 | all the source code for all modules it contains, plus any associated
139 | interface definition files, plus the scripts used to control compilation
140 | and installation of the library.
141 | 
142 |   Activities other than copying, distribution and modification are not
143 | covered by this License; they are outside its scope.  The act of
144 | running a program using the Library is not restricted, and output from
145 | such a program is covered only if its contents constitute a work based
146 | on the Library (independent of the use of the Library in a tool for
147 | writing it).  Whether that is true depends on what the Library does
148 | and what the program that uses the Library does.
149 | 
150 |   1. You may copy and distribute verbatim copies of the Library's
151 | complete source code as you receive it, in any medium, provided that
152 | you conspicuously and appropriately publish on each copy an
153 | appropriate copyright notice and disclaimer of warranty; keep intact
154 | all the notices that refer to this License and to the absence of any
155 | warranty; and distribute a copy of this License along with the
156 | Library.
157 | 
158 |   You may charge a fee for the physical act of transferring a copy,
159 | and you may at your option offer warranty protection in exchange for a
160 | fee.
161 | 
162 |   2. You may modify your copy or copies of the Library or any portion
163 | of it, thus forming a work based on the Library, and copy and
164 | distribute such modifications or work under the terms of Section 1
165 | above, provided that you also meet all of these conditions:
166 | 
167 |     a) The modified work must itself be a software library.
168 | 
169 |     b) You must cause the files modified to carry prominent notices
170 |     stating that you changed the files and the date of any change.
171 | 
172 |     c) You must cause the whole of the work to be licensed at no
173 |     charge to all third parties under the terms of this License.
174 | 
175 |     d) If a facility in the modified Library refers to a function or a
176 |     table of data to be supplied by an application program that uses
177 |     the facility, other than as an argument passed when the facility
178 |     is invoked, then you must make a good faith effort to ensure that,
179 |     in the event an application does not supply such function or
180 |     table, the facility still operates, and performs whatever part of
181 |     its purpose remains meaningful.
182 | 
183 |     (For example, a function in a library to compute square roots has
184 |     a purpose that is entirely well-defined independent of the
185 |     application.  Therefore, Subsection 2d requires that any
186 |     application-supplied function or table used by this function must
187 |     be optional: if the application does not supply it, the square
188 |     root function must still compute square roots.)
189 | 
190 | These requirements apply to the modified work as a whole.  If
191 | identifiable sections of that work are not derived from the Library,
192 | and can be reasonably considered independent and separate works in
193 | themselves, then this License, and its terms, do not apply to those
194 | sections when you distribute them as separate works.  But when you
195 | distribute the same sections as part of a whole which is a work based
196 | on the Library, the distribution of the whole must be on the terms of
197 | this License, whose permissions for other licensees extend to the
198 | entire whole, and thus to each and every part regardless of who wrote
199 | it.
200 | 
201 | Thus, it is not the intent of this section to claim rights or contest
202 | your rights to work written entirely by you; rather, the intent is to
203 | exercise the right to control the distribution of derivative or
204 | collective works based on the Library.
205 | 
206 | In addition, mere aggregation of another work not based on the Library
207 | with the Library (or with a work based on the Library) on a volume of
208 | a storage or distribution medium does not bring the other work under
209 | the scope of this License.
210 | 
211 |   3. You may opt to apply the terms of the ordinary GNU General Public
212 | License instead of this License to a given copy of the Library.  To do
213 | this, you must alter all the notices that refer to this License, so
214 | that they refer to the ordinary GNU General Public License, version 2,
215 | instead of to this License.  (If a newer version than version 2 of the
216 | ordinary GNU General Public License has appeared, then you can specify
217 | that version instead if you wish.)  Do not make any other change in
218 | these notices.
219 | 
220 |   Once this change is made in a given copy, it is irreversible for
221 | that copy, so the ordinary GNU General Public License applies to all
222 | subsequent copies and derivative works made from that copy.
223 | 
224 |   This option is useful when you wish to copy part of the code of
225 | the Library into a program that is not a library.
226 | 
227 |   4. You may copy and distribute the Library (or a portion or
228 | derivative of it, under Section 2) in object code or executable form
229 | under the terms of Sections 1 and 2 above provided that you accompany
230 | it with the complete corresponding machine-readable source code, which
231 | must be distributed under the terms of Sections 1 and 2 above on a
232 | medium customarily used for software interchange.
233 | 
234 |   If distribution of object code is made by offering access to copy
235 | from a designated place, then offering equivalent access to copy the
236 | source code from the same place satisfies the requirement to
237 | distribute the source code, even though third parties are not
238 | compelled to copy the source along with the object code.
239 | 
240 |   5. A program that contains no derivative of any portion of the
241 | Library, but is designed to work with the Library by being compiled or
242 | linked with it, is called a "work that uses the Library".  Such a
243 | work, in isolation, is not a derivative work of the Library, and
244 | therefore falls outside the scope of this License.
245 | 
246 |   However, linking a "work that uses the Library" with the Library
247 | creates an executable that is a derivative of the Library (because it
248 | contains portions of the Library), rather than a "work that uses the
249 | library".  The executable is therefore covered by this License.
250 | Section 6 states terms for distribution of such executables.
251 | 
252 |   When a "work that uses the Library" uses material from a header file
253 | that is part of the Library, the object code for the work may be a
254 | derivative work of the Library even though the source code is not.
255 | Whether this is true is especially significant if the work can be
256 | linked without the Library, or if the work is itself a library.  The
257 | threshold for this to be true is not precisely defined by law.
258 | 
259 |   If such an object file uses only numerical parameters, data
260 | structure layouts and accessors, and small macros and small inline
261 | functions (ten lines or less in length), then the use of the object
262 | file is unrestricted, regardless of whether it is legally a derivative
263 | work.  (Executables containing this object code plus portions of the
264 | Library will still fall under Section 6.)
265 | 
266 |   Otherwise, if the work is a derivative of the Library, you may
267 | distribute the object code for the work under the terms of Section 6.
268 | Any executables containing that work also fall under Section 6,
269 | whether or not they are linked directly with the Library itself.
270 | 
271 |   6. As an exception to the Sections above, you may also combine or
272 | link a "work that uses the Library" with the Library to produce a
273 | work containing portions of the Library, and distribute that work
274 | under terms of your choice, provided that the terms permit
275 | modification of the work for the customer's own use and reverse
276 | engineering for debugging such modifications.
277 | 
278 |   You must give prominent notice with each copy of the work that the
279 | Library is used in it and that the Library and its use are covered by
280 | this License.  You must supply a copy of this License.  If the work
281 | during execution displays copyright notices, you must include the
282 | copyright notice for the Library among them, as well as a reference
283 | directing the user to the copy of this License.  Also, you must do one
284 | of these things:
285 | 
286 |     a) Accompany the work with the complete corresponding
287 |     machine-readable source code for the Library including whatever
288 |     changes were used in the work (which must be distributed under
289 |     Sections 1 and 2 above); and, if the work is an executable linked
290 |     with the Library, with the complete machine-readable "work that
291 |     uses the Library", as object code and/or source code, so that the
292 |     user can modify the Library and then relink to produce a modified
293 |     executable containing the modified Library.  (It is understood
294 |     that the user who changes the contents of definitions files in the
295 |     Library will not necessarily be able to recompile the application
296 |     to use the modified definitions.)
297 | 
298 |     b) Use a suitable shared library mechanism for linking with the
299 |     Library.  A suitable mechanism is one that (1) uses at run time a
300 |     copy of the library already present on the user's computer system,
301 |     rather than copying library functions into the executable, and (2)
302 |     will operate properly with a modified version of the library, if
303 |     the user installs one, as long as the modified version is
304 |     interface-compatible with the version that the work was made with.
305 | 
306 |     c) Accompany the work with a written offer, valid for at
307 |     least three years, to give the same user the materials
308 |     specified in Subsection 6a, above, for a charge no more
309 |     than the cost of performing this distribution.
310 | 
311 |     d) If distribution of the work is made by offering access to copy
312 |     from a designated place, offer equivalent access to copy the above
313 |     specified materials from the same place.
314 | 
315 |     e) Verify that the user has already received a copy of these
316 |     materials or that you have already sent this user a copy.
317 | 
318 |   For an executable, the required form of the "work that uses the
319 | Library" must include any data and utility programs needed for
320 | reproducing the executable from it.  However, as a special exception,
321 | the materials to be distributed need not include anything that is
322 | normally distributed (in either source or binary form) with the major
323 | components (compiler, kernel, and so on) of the operating system on
324 | which the executable runs, unless that component itself accompanies
325 | the executable.
326 | 
327 |   It may happen that this requirement contradicts the license
328 | restrictions of other proprietary libraries that do not normally
329 | accompany the operating system.  Such a contradiction means you cannot
330 | use both them and the Library together in an executable that you
331 | distribute.
332 | 
333 |   7. You may place library facilities that are a work based on the
334 | Library side-by-side in a single library together with other library
335 | facilities not covered by this License, and distribute such a combined
336 | library, provided that the separate distribution of the work based on
337 | the Library and of the other library facilities is otherwise
338 | permitted, and provided that you do these two things:
339 | 
340 |     a) Accompany the combined library with a copy of the same work
341 |     based on the Library, uncombined with any other library
342 |     facilities.  This must be distributed under the terms of the
343 |     Sections above.
344 | 
345 |     b) Give prominent notice with the combined library of the fact
346 |     that part of it is a work based on the Library, and explaining
347 |     where to find the accompanying uncombined form of the same work.
348 | 
349 |   8. You may not copy, modify, sublicense, link with, or distribute
350 | the Library except as expressly provided under this License.  Any
351 | attempt otherwise to copy, modify, sublicense, link with, or
352 | distribute the Library is void, and will automatically terminate your
353 | rights under this License.  However, parties who have received copies,
354 | or rights, from you under this License will not have their licenses
355 | terminated so long as such parties remain in full compliance.
356 | 
357 |   9. You are not required to accept this License, since you have not
358 | signed it.  However, nothing else grants you permission to modify or
359 | distribute the Library or its derivative works.  These actions are
360 | prohibited by law if you do not accept this License.  Therefore, by
361 | modifying or distributing the Library (or any work based on the
362 | Library), you indicate your acceptance of this License to do so, and
363 | all its terms and conditions for copying, distributing or modifying
364 | the Library or works based on it.
365 | 
366 |   10. Each time you redistribute the Library (or any work based on the
367 | Library), the recipient automatically receives a license from the
368 | original licensor to copy, distribute, link with or modify the Library
369 | subject to these terms and conditions.  You may not impose any further
370 | restrictions on the recipients' exercise of the rights granted herein.
371 | You are not responsible for enforcing compliance by third parties with
372 | this License.
373 | 
374 |   11. If, as a consequence of a court judgment or allegation of patent
375 | infringement or for any other reason (not limited to patent issues),
376 | conditions are imposed on you (whether by court order, agreement or
377 | otherwise) that contradict the conditions of this License, they do not
378 | excuse you from the conditions of this License.  If you cannot
379 | distribute so as to satisfy simultaneously your obligations under this
380 | License and any other pertinent obligations, then as a consequence you
381 | may not distribute the Library at all.  For example, if a patent
382 | license would not permit royalty-free redistribution of the Library by
383 | all those who receive copies directly or indirectly through you, then
384 | the only way you could satisfy both it and this License would be to
385 | refrain entirely from distribution of the Library.
386 | 
387 | If any portion of this section is held invalid or unenforceable under any
388 | particular circumstance, the balance of the section is intended to apply,
389 | and the section as a whole is intended to apply in other circumstances.
390 | 
391 | It is not the purpose of this section to induce you to infringe any
392 | patents or other property right claims or to contest validity of any
393 | such claims; this section has the sole purpose of protecting the
394 | integrity of the free software distribution system which is
395 | implemented by public license practices.  Many people have made
396 | generous contributions to the wide range of software distributed
397 | through that system in reliance on consistent application of that
398 | system; it is up to the author/donor to decide if he or she is willing
399 | to distribute software through any other system and a licensee cannot
400 | impose that choice.
401 | 
402 | This section is intended to make thoroughly clear what is believed to
403 | be a consequence of the rest of this License.
404 | 
405 |   12. If the distribution and/or use of the Library is restricted in
406 | certain countries either by patents or by copyrighted interfaces, the
407 | original copyright holder who places the Library under this License may add
408 | an explicit geographical distribution limitation excluding those countries,
409 | so that distribution is permitted only in or among countries not thus
410 | excluded.  In such case, this License incorporates the limitation as if
411 | written in the body of this License.
412 | 
413 |   13. The Free Software Foundation may publish revised and/or new
414 | versions of the Lesser General Public License from time to time.
415 | Such new versions will be similar in spirit to the present version,
416 | but may differ in detail to address new problems or concerns.
417 | 
418 | Each version is given a distinguishing version number.  If the Library
419 | specifies a version number of this License which applies to it and
420 | "any later version", you have the option of following the terms and
421 | conditions either of that version or of any later version published by
422 | the Free Software Foundation.  If the Library does not specify a
423 | license version number, you may choose any version ever published by
424 | the Free Software Foundation.
425 | 
426 |   14. If you wish to incorporate parts of the Library into other free
427 | programs whose distribution conditions are incompatible with these,
428 | write to the author to ask for permission.  For software which is
429 | copyrighted by the Free Software Foundation, write to the Free
430 | Software Foundation; we sometimes make exceptions for this.  Our
431 | decision will be guided by the two goals of preserving the free status
432 | of all derivatives of our free software and of promoting the sharing
433 | and reuse of software generally.
434 | 
435 |                             NO WARRANTY
436 | 
437 |   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443 | PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444 | LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446 | 
447 |   16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456 | DAMAGES.
457 | 
458 |                      END OF TERMS AND CONDITIONS
459 | 
460 |            How to Apply These Terms to Your New Libraries
461 | 
462 |   If you develop a new library, and you want it to be of the greatest
463 | possible use to the public, we recommend making it free software that
464 | everyone can redistribute and change.  You can do so by permitting
465 | redistribution under these terms (or, alternatively, under the terms of the
466 | ordinary General Public License).
467 | 
468 |   To apply these terms, attach the following notices to the library.  It is
469 | safest to attach them to the start of each source file to most effectively
470 | convey the exclusion of warranty; and each file should have at least the
471 | "copyright" line and a pointer to where the full notice is found.
472 | 
473 |     <one line to give the library's name and a brief idea of what it does.>
474 |     Copyright (C) <year>  <name of author>
475 | 
476 |     This library is free software; you can redistribute it and/or
477 |     modify it under the terms of the GNU Lesser General Public
478 |     License as published by the Free Software Foundation; either
479 |     version 2.1 of the License, or (at your option) any later version.
480 | 
481 |     This library is distributed in the hope that it will be useful,
482 |     but WITHOUT ANY WARRANTY; without even the implied warranty of
483 |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
484 |     Lesser General Public License for more details.
485 | 
486 |     You should have received a copy of the GNU Lesser General Public
487 |     License along with this library; if not, write to the Free Software
488 |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
489 | 
490 | Also add information on how to contact you by electronic and paper mail.
491 | 
492 | You should also get your employer (if you work as a programmer) or your
493 | school, if any, to sign a "copyright disclaimer" for the library, if
494 | necessary.  Here is a sample; alter the names:
495 | 
496 |   Yoyodyne, Inc., hereby disclaims all copyright interest in the
497 |   library `Frob' (a library for tweaking knobs) written by James Random Hacker.
498 | 
499 |   <signature of Ty Coon>, 1 April 1990
500 |   Ty Coon, President of Vice
501 | 
502 | That's all there is to it!


--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
 1 | AUTOMAKE_OPTIONS = foreign
 2 | ACLOCAL_AMFLAGS = -I m4
 3 | SUBDIRS = src include tools udev
 4 | 
 5 | EXTRA_DIST = \
 6 | 	README.md \
 7 | 	git-version-gen
 8 | 
 9 | dist-hook:
10 | 	@if ! git diff --quiet; then echo "Uncommitted changes present; not releasing"; exit 1; fi
11 | 	echo $(VERSION) > $(distdir)/.tarball-version
12 | 
13 | DISTCHECK_CONFIGURE_FLAGS = \
14 | 	--with-udevrulesdir=$dc_install_base/$(udevrulesdir)
15 | 


--------------------------------------------------------------------------------
/NEWS:
--------------------------------------------------------------------------------
  1 | Version 1.3.1
  2 | ~~~~~~~~~~~~~
  3 | 
  4 | * Device database changes:
  5 |   - Support iPad Pro M5 family devices
  6 |   - Support Apple Vision Pro M5
  7 |   - Support MacBook Pro 14-inch M5
  8 | 
  9 | * Bug Fixes:
 10 |     Fix: array initialization compatibility with MSVC
 11 | 
 12 | 
 13 | Version 1.3.0
 14 | ~~~~~~~~~~~~~
 15 | 
 16 | * Changes:
 17 |   - Switch to better initializer strategy
 18 |   - Allow building without readline support for the irecovery tool
 19 |   - Added support for iOS 1 and iOS 2 recovery mode (Linux, macOS)
 20 | 
 21 | * Device database changes:
 22 |   - Support iPhone 17 family devices
 23 |   - Support Watch 11 / SE3 / Ultra3 models
 24 |   - Support March 2025 iPad and Mac models
 25 |   - Support iPhone 16e
 26 |   - Support November 2024 Mac models
 27 |   - Support iPad mini (A17 Pro)
 28 | 
 29 | * Bug Fixes:
 30 |   - IOKit: Fix race condition when trying to delete runloop before it even started
 31 | 
 32 | 
 33 | Version 1.2.1
 34 | ~~~~~~~~~~~~~
 35 | 
 36 | * Changes:
 37 |   - Make sure IRECV_DEVICE_REMOVE event has the mode set the device was in
 38 |   - KIS: Add some retry loops around open/set config/set interface operations
 39 | 
 40 | * Device database changes:
 41 |   - Support Apple Watch Series 10 and iPhone 16 models
 42 |   - Add iPad Air (M2) and iPad Pro (M4) models
 43 | 
 44 | * Bug Fixes:
 45 |   - Windows: Fix crash due to access to uninitialized data
 46 | 
 47 | 
 48 | Version 1.2.0
 49 | ~~~~~~~~~~~~~
 50 | 
 51 | * Changes:
 52 |   - Allow building --without-tools
 53 |   - Add KIS (aka Debug USB) support for macOS, Linux, and Windows
 54 |     (Windows note: requires up-to-date AppleMobileDeviceSupport64.msi package installed)
 55 |   - Add Port DFU support (restore procedure is handled externally)
 56 |   - irecovery: Print detailed mode for -q and -m commands
 57 |   - Overall code cleanup and de-duplication
 58 |   - Windows-specific code cleanup and improvements
 59 | 
 60 | * Device database changes:
 61 |   - Add Mac Pro, Mac Studio (M2) and MacBook Air (M2) models
 62 |   - Add iPhone 15 family
 63 |   - Add Apple Watch Series 9 and Ultra 2 models
 64 |   - Add November 2023 iMac and MacBook Pro models
 65 |   - Add support for Apple Vision Pro (RealityDevice14,1)
 66 | 
 67 | * Bug Fixes:
 68 |   - A few minor Windows-specific bug fixes
 69 | 
 70 | Version 1.1.0
 71 | ~~~~~~~~~~~~~
 72 | 
 73 | * Changes:
 74 |   - Remove duplicated thread/collection code and use new libimobiledevice-glue instead
 75 |   - Add new `irecv_send_command_breq` (for M1 restoring)
 76 |   - Add new `setenvnp` command
 77 |   - Add support for iPad 8 and iPad Air 4 models
 78 |   - Add all current Apple Watch models (device lookup)
 79 |   - Add support for HomePod and HomePod mini (device lookup)
 80 |   - Add support for Apple Silicon/M1 Macs (device lookup) and remaining T2/iBridge devices
 81 |   - Add iMac 24-inch M1 models
 82 |   - Add iPad Pro 11-inch (3rd gen) and iPad Pro 12.9-inch (5th gen) devices
 83 |   - Add Apple TV 4K (2nd gen)
 84 |   - Add iPhone 13 family
 85 |   - Add 9th gen iPad devices
 86 |   - Add 6th gen iPad mini
 87 |   - Add Apple Watch Series 7
 88 |   - Add MacBook Pro 2021 models (device lookup)
 89 |   - Add iPad Air (5th gen)
 90 |   - Add iPhone SE (3rd gen)
 91 |   - Add Mac Studio
 92 |   - Add Studio Display (device lookup)
 93 |   - Add device ID for macOS 12 Apple Silicon VMs
 94 |   - Add M2 MacBook models
 95 |   - Add iPhone 14 family
 96 |   - Add Apple Watch SE 2, Series 8 and Ultra family
 97 |   - Add iPad (10th gen)
 98 |   - Add iPad Pro 11-inch (4th gen) and iPad Pro 12.9-inch (6th gen)
 99 |   - Add Apple TV 4K 3rd gen
100 |   - Add January 2023 Macs and 2nd generation HomePod models
101 |   - [Windows] Add support for newer drivers
102 |   - irecovery: Add new "--devices" option to list internal device data
103 |   - irecovery: Output product, model and marketing name for device information
104 | 
105 | * Bug Fixes:
106 |   - Send a ZLP in recovery mode if the buffer size is a multiple of 512
107 |   - Make sure DEVICE_ADD events are sent to additional event listeners
108 |   - [Windows] Use ANSI versions for SetupDI and CreateFile API to prevent errors when compiling with unicode support
109 |   - irecovery: Fix sending certain commands
110 | 
111 | Version 1.0.0
112 | ~~~~~~~~~~~~~
113 | 
114 | * Changes:
115 |   - Output basic device information after connecting
116 |   - Remove obsolete "in-tree" copy of libusb-1.0
117 |   - Improve source code directory structure
118 |   - Clean up and update of build system files
119 |   - Major code refactoring
120 |   - Add getters to retrieve device model information
121 |   - Change exploit related wording to more accurate limera1n
122 |   - Various improvements/fixes for win32 build
123 |   - Add support for latest device models
124 |   - Fix some memory leaks
125 |   - Add requirement for autoconf 2.64
126 |   - Support IOKit on OSX (removes dependency on libusb)
127 |   - Add DFU mode error handling
128 |   - Add udev rules to allow non-root device access
129 |   - Support ECID in hex or decimal format
130 |   - Fix various compiler warnings
131 |   - Add device add/remove event subscription interface
132 |   - Convert README to markdown
133 |   - Print PWND string if present
134 |   - Add support for Apple T2 processors
135 |   - Allow compiling without USB functionality
136 |   - Support checkra1n DFU mode devices
137 |   - Allow toggling debug level using "LIBIRECOVERY_DEBUG_LEVEL" environment
138 |     variable
139 |   - Add long argument name variants to irecovery
140 |   - Add new "--version" argument to irecovery
141 |   - Add support for Apple Watch 1st gen devices
142 |   - Add support for missing iPad4,3 model and fix wrong device information
143 |     iPad7 variants
144 |   - Improve README.md with project description, installation, contributing and
145 |     usage sections
146 |   - Rename library and all related files by adding an API version resulting
147 |     in "libirecovery-1.0"
148 | 
149 | Version 0.1.1
150 | ~~~~~~~~~~~~~
151 | 
152 | * Changes:
153 |   - Add serial number and imei getters
154 |   - Improve USB communication stability
155 |   - Add support for WTF mode
156 |   - Add option to target device by ECID
157 |   - Add nonce getter
158 |   - Improve win32 device detection and mingw compatibility
159 |   - Add support for new device models
160 |   - Switch to autotools build system instead of plain Makefile
161 |   - Expose control and bulk transfer methods in public interface
162 |   - Improve maintainability of device model information
163 |   - Change license to LGPL 2.1
164 | 
165 | Version 0.1.0
166 | ~~~~~~~~~~~~~
167 | 
168 | * Changes:
169 |   - Implement initial interface and device communication
170 |   - Add basic irecovery tool
171 |   - Setup build system
172 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | # libirecovery
  2 | 
  3 | *The libirecovery library allows communication with iBoot/iBSS of iOS devices
  4 | via USB.*
  5 | 
  6 | ![](https://github.com/libimobiledevice/libirecovery/workflows/build/badge.svg)
  7 | 
  8 | ## Table of Contents
  9 | - [Features](#features)
 10 | - [Building](#building)
 11 |   - [Prerequisites](#prerequisites)
 12 |     - [Linux (Debian/Ubuntu based)](#linux-debianubuntu-based)
 13 |     - [macOS](#macos)
 14 |     - [Windows](#windows)
 15 |   - [Configuring the source tree](#configuring-the-source-tree)
 16 |   - [Building and installation](#building-and-installation)
 17 | - [Usage](#usage)
 18 | - [Contributing](#contributing)
 19 | - [Links](#links)
 20 | - [License](#license)
 21 | - [Credits](#credits)
 22 | 
 23 | ## Features
 24 | 
 25 | libirecovery is a cross-platform library which implements communication to
 26 | iBoot/iBSS found on Apple's iOS devices via USB. A command-line utility named
 27 | `irecovery` is also provided.
 28 | 
 29 | This is a fork of an older version from former openjailbreak.org and is meant to
 30 | be used with [idevicerestore](https://github.com/libimobiledevice/idevicerestore.git/) from the [libimobiledevice](https://github.com/libimobiledevice/) project.
 31 | 
 32 | ## Building
 33 | 
 34 | ### Prerequisites
 35 | 
 36 | You need to have a working compiler (gcc/clang) and development environent
 37 | available. This project uses autotools for the build process, allowing to
 38 | have common build steps across different platforms.
 39 | Only the prerequisites differ and they are described in this section.
 40 | 
 41 | libirecovery requires [libimobiledevice-glue](https://github.com/libimobiledevice/libimobiledevice-glue).
 42 | Some platforms already provide it as a package.
 43 | Check the [Building](https://github.com/libimobiledevice/libimobiledevice-glue?tab=readme-ov-file#building)
 44 | section of the README on how to build it.
 45 | 
 46 | #### Linux (Debian/Ubuntu based)
 47 | 
 48 | * Install all required dependencies and build tools:
 49 |   ```shell
 50 |   sudo apt-get install \
 51 |   	build-essential \
 52 |   	pkg-config \	
 53 |   	checkinstall \
 54 |   	git \
 55 |   	autoconf \
 56 |   	automake \
 57 |   	libtool-bin \
 58 |   	libimobiledevice-glue-dev \
 59 |   	libreadline-dev \
 60 |   	libusb-1.0-0-dev
 61 |   ```
 62 | 
 63 |   In case libimobiledevice-glue-dev is not available, you can manually build and install it. See note above.
 64 | 
 65 | #### macOS
 66 | 
 67 | * Make sure the Xcode command line tools are installed. Then, use either [MacPorts](https://www.macports.org/)
 68 |   or [Homebrew](https://brew.sh/) to install `automake`, `autoconf`, `libtool`, etc.
 69 | 
 70 |   Using MacPorts:
 71 |   ```shell
 72 |   sudo port install libtool autoconf automake pkgconfig libimobiledevice-glue
 73 |   ```
 74 | 
 75 |   Using Homebrew:
 76 |   ```shell
 77 |   brew install libtool autoconf automake pkg-config libimobiledevice-glue
 78 |   ```
 79 | 
 80 | #### Windows
 81 | 
 82 | * Using [MSYS2](https://www.msys2.org/) is the official way of compiling this project on Windows. Download the MSYS2 installer
 83 |   and follow the installation steps.
 84 | 
 85 |   It is recommended to use the _MSYS2 MinGW 64-bit_ shell. Run it and make sure the required dependencies are installed:
 86 | 
 87 |   ```shell
 88 |   pacman -S base-devel \
 89 |   	git \
 90 |   	mingw-w64-x86_64-gcc \
 91 |   	make \
 92 |   	libtool \
 93 |   	autoconf \
 94 |   	automake-wrapper \
 95 |   	pkg-config \
 96 |   	mingw-w64-x86_64-libimobiledevice-glue \
 97 |   	mingw-w64-x86_64-readline
 98 |   ```
 99 |   NOTE: You can use a different shell and different compiler according to your needs. Adapt the above command accordingly.
100 | 
101 | ### Configuring the source tree
102 | 
103 | You can build the source code from a git checkout, or from a `.tar.bz2` release tarball from [Releases](https://github.com/libimobiledevice/libirecovery/releases).
104 | Before we can build it, the source tree has to be configured for building. The steps depend on where you got the source from.
105 | 
106 | Since libirecovery depends on other packages, you should set the pkg-config environment variable `PKG_CONFIG_PATH`
107 | accordingly. Make sure to use a path with the same prefix as the dependencies. If they are installed in `/usr/local` you would do
108 | 
109 | ```shell
110 | export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
111 | ```
112 | 
113 | * **From git**
114 | 
115 |   If you haven't done already, clone the actual project repository and change into the directory.
116 |   ```shell
117 |   git clone https://github.com/libimobiledevice/libirecovery
118 |   cd libirecovery
119 |   ```
120 | 
121 |   Configure the source tree for building:
122 |   ```shell
123 |   ./autogen.sh
124 |   ```
125 | 
126 | * **From release tarball (.tar.bz2)**
127 | 
128 |   When using an official [release tarball](https://github.com/libimobiledevice/libirecovery/releases) (`libirecovery-x.y.z.tar.bz2`)
129 |   the procedure is slightly different.
130 | 
131 |   Extract the tarball:
132 |   ```shell
133 |   tar xjf libirecovery-x.y.z.tar.bz2
134 |   cd libirecovery-x.y.z
135 |   ```
136 | 
137 |   Configure the source tree for building:
138 |   ```shell
139 |   ./configure
140 |   ```
141 | 
142 | Both `./configure` and `./autogen.sh` (which generates and calls `configure`) accept a few options, for example `--prefix` to allow
143 | building for a different target folder. You can simply pass them like this:
144 | 
145 | ```shell
146 | ./autogen.sh --prefix=/usr/local
147 | ```
148 | or
149 | ```shell
150 | ./configure --prefix=/usr/local
151 | ```
152 | 
153 | Once the command is successful, the last few lines of output will look like this:
154 | ```
155 | [...]
156 | config.status: creating config.h
157 | config.status: executing depfiles commands
158 | config.status: executing libtool commands
159 | 
160 | Configuration for libirecovery 1.2.0:
161 | -------------------------------------------
162 | 
163 |   Install prefix: .........: /usr/local
164 |   USB backend: ............: IOKit
165 | 
166 |   Now type 'make' to build libirecovery 1.2.0,
167 |   and then 'make install' for installation.
168 | ```
169 | 
170 | ### Building and installation
171 | 
172 | If you followed all the steps successfully, and `autogen.sh` or `configure` did not print any errors,
173 | you are ready to build the project. This is simply done with
174 | 
175 | ```shell
176 | make
177 | ```
178 | 
179 | If no errors are emitted you are ready for installation. Depending on whether
180 | the current user has permissions to write to the destination directory or not,
181 | you would either run
182 | ```shell
183 | make install
184 | ```
185 | _OR_
186 | ```shell
187 | sudo make install
188 | ```
189 | 
190 | If you are on Linux, you want to run `sudo ldconfig` after installation to
191 | make sure the installed libraries are made available.
192 | 
193 | ## Usage
194 | 
195 | First of all attach your device to your machine. Make sure your device is not
196 | in normal mode. You can use the `ideviceenterrecovery` application from
197 | [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice.git/)
198 | to let your device boot into recovery mode if you need it.
199 | 
200 | Then simply run:
201 | ```shell
202 | irecovery --shell
203 | ```
204 | 
205 | This connects to your device and opens a simple shell to interact with the
206 | device.
207 | 
208 | For instance to make your device boot into normal mode again use:
209 | ```shell
210 | setenv auto-boot true
211 | saveenv
212 | reboot
213 | ```
214 | 
215 | Please consult the usage information or manual page for a full documentation of
216 | available command line options:
217 | ```shell
218 | irecovery --help
219 | man irecovery
220 | ```
221 | 
222 | ## Contributing
223 | 
224 | We welcome contributions from anyone and are grateful for every pull request!
225 | 
226 | If you'd like to contribute, please fork the `master` branch, change, commit and
227 | send a pull request for review. Once approved it can be merged into the main
228 | code base.
229 | 
230 | If you plan to contribute larger changes or a major refactoring, please create a
231 | ticket first to discuss the idea upfront to ensure less effort for everyone.
232 | 
233 | Please make sure your contribution adheres to:
234 | * Try to follow the code style of the project
235 | * Commit messages should describe the change well without being too short
236 | * Try to split larger changes into individual commits of a common domain
237 | * Use your real name and a valid email address for your commits
238 | 
239 | ## Links
240 | 
241 | * Homepage: https://libimobiledevice.org/
242 | * Repository: https://github.com/libimobiledevice/libirecovery.git
243 | * Repository (Mirror): https://git.libimobiledevice.org/libirecovery.git
244 | * Issue Tracker: https://github.com/libimobiledevice/libirecovery/issues
245 | * Mailing List: https://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel
246 | * Twitter: https://twitter.com/libimobiledev
247 | 
248 | ## License
249 | 
250 | This project is licensed under the [GNU Lesser General Public License v2.1](https://www.gnu.org/licenses/lgpl-2.1.en.html),
251 | also included in the repository in the `COPYING` file.
252 | 
253 | ## Credits
254 | 
255 | Apple, iPhone, iPad, iPod, iPod Touch, Apple TV, Apple Watch, Mac, iOS,
256 | iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc.
257 | 
258 | This project is an independent software library and has not been authorized,
259 | sponsored, or otherwise approved by Apple Inc.
260 | 
261 | README Updated on: 2025-09-10
262 | 


--------------------------------------------------------------------------------
/autogen.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | olddir=`pwd`
 4 | srcdir=`dirname $0`
 5 | test -z "$srcdir" && srcdir=.
 6 | 
 7 | (
 8 |   cd "$srcdir"
 9 | 
10 |   gprefix=`which glibtoolize 2>&1 >/dev/null`
11 |   if [ $? -eq 0 ]; then
12 |     glibtoolize --force
13 |   else
14 |     libtoolize --force
15 |   fi
16 |   aclocal -I m4
17 |   autoheader
18 |   automake --add-missing
19 |   autoconf
20 | 
21 |   cd "$olddir"
22 | )
23 | 
24 | if [ -z "$NOCONFIGURE" ]; then
25 |   $srcdir/configure "$@"
26 | fi
27 | 


--------------------------------------------------------------------------------
/configure.ac:
--------------------------------------------------------------------------------
  1 | #                                               -*- Autoconf -*-
  2 | # Process this file with autoconf to produce a configure script.
  3 | 
  4 | AC_PREREQ(2.68)
  5 | AC_INIT([libirecovery], [m4_esyscmd(./git-version-gen $RELEASE_VERSION)], [https://github.com/libimobiledevice/libirecovery/issues], [], [https://libimobiledevice.org])
  6 | AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip check-news])
  7 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
  8 | AC_CONFIG_SRCDIR([src/])
  9 | AC_CONFIG_HEADERS([config.h])
 10 | AC_CONFIG_MACRO_DIR([m4])
 11 | 
 12 | dnl libtool versioning
 13 | # +1 : 0 : +1  == adds new functions to the interface
 14 | # +1 : 0 : 0   == changes or removes functions (changes include both
 15 | #                 changes to the signature and the semantic)
 16 | #  ? :+1 : ?   == just internal changes
 17 | # CURRENT : REVISION : AGE
 18 | LIBIRECOVERY_SO_VERSION=6:2:1
 19 | 
 20 | dnl Minimum package versions
 21 | LIBUSB_VERSION=1.0.3
 22 | LIMD_GLUE_VERSION=1.2.0
 23 | 
 24 | AC_SUBST(LIBIRECOVERY_SO_VERSION)
 25 | AC_SUBST(LIMD_GLUE_VERSION)
 26 | 
 27 | # Checks for programs.
 28 | AC_PROG_CC
 29 | #AC_PROG_CXX
 30 | AM_PROG_CC_C_O
 31 | LT_INIT
 32 | 
 33 | # Checks for libraries.
 34 | PKG_CHECK_MODULES(limd_glue, libimobiledevice-glue-1.0 >= $LIMD_GLUE_VERSION)
 35 | 
 36 | # Checks for header files.
 37 | AC_CHECK_HEADERS([stdint.h stdlib.h string.h])
 38 | 
 39 | # Checks for typedefs, structures, and compiler characteristics.
 40 | AC_C_CONST
 41 | AC_TYPE_SIZE_T
 42 | AC_TYPE_SSIZE_T
 43 | AC_TYPE_UINT16_T
 44 | AC_TYPE_UINT32_T
 45 | AC_TYPE_UINT8_T
 46 | 
 47 | # Checks for library functions.
 48 | AC_CHECK_FUNCS([strdup strerror strcasecmp strndup malloc realloc calloc])
 49 | 
 50 | # Check additional platform flags
 51 | AC_MSG_CHECKING([for platform-specific build settings])
 52 | case ${host_os} in
 53 | 	darwin*)
 54 | 		AC_MSG_RESULT([${host_os}])
 55 | 		AC_CHECK_HEADER(CoreFoundation/CoreFoundation.h, [
 56 | 			AC_CHECK_HEADER(IOKit/usb/IOUSBLib.h, [
 57 | 				GLOBAL_LDFLAGS+=" -framework IOKit -framework CoreFoundation"
 58 | 				have_iokit=yes
 59 | 			], [])
 60 | 		], [])
 61 | 	;;
 62 | 	mingw32*)
 63 | 		AC_MSG_RESULT([${host_os}])
 64 | 		GLOBAL_LDFLAGS+=" -static-libgcc -lkernel32 -lsetupapi"
 65 | 		win32=true
 66 | 	;;
 67 | 	cygwin*)
 68 | 		AC_MSG_RESULT([${host_os}])
 69 | 		CC=gcc-3
 70 | 		CFLAGS+=" -mno-cygwin"
 71 | 		GLOBAL_LDFLAGS+=" -static-libgcc -lkernel32 -lsetupapi"
 72 | 		win32=true
 73 | 	;;
 74 | 	*)
 75 | 		AC_MSG_RESULT([${host_os}])
 76 | 	;;
 77 | esac
 78 | AM_CONDITIONAL(WIN32, test x$win32 = xtrue)
 79 | 
 80 | AC_ARG_WITH([tools],
 81 | 	[AS_HELP_STRING([--with-tools], [Build irecovery tools. [default=yes]])],
 82 | 	[],
 83 | 	[with_tools=yes])
 84 | 
 85 | AS_IF([test "x$with_tools" = "xyes"], [
 86 | 	have_readline=no
 87 | 	AC_DEFINE(BUILD_TOOLS, 1, [Define if we are building irecovery tools])
 88 | 	AC_CHECK_HEADERS([readline/readline.h],
 89 | 		[AC_DEFINE(HAVE_READLINE, 1, [Define if readline is available])
 90 | 		have_readline=yes],
 91 | 		[AC_MSG_NOTICE([NOTE: Building without readline support. If you want readline support, install its development package.])]
 92 | 	)
 93 | 	AM_CONDITIONAL(HAVE_READLINE, test "x$have_readline" = "xyes")
 94 | ])
 95 | AM_CONDITIONAL(BUILD_TOOLS, test "x$with_tools" = "xyes")
 96 | 
 97 | AC_ARG_WITH([dummy],
 98 | 	[AS_HELP_STRING([--with-dummy], [Use no USB driver at all [default=no]. This is only useful if you just want to query the device list by product type or hardware model. All other operations are no-ops or will return IRECV_E_UNSUPPORTED.])],
 99 | 	[],
100 | 	[with_dummy=no])
101 | 
102 | AS_IF([test "x$have_iokit" = "xyes"], [
103 | 	AC_ARG_WITH([iokit],
104 | 		[AS_HELP_STRING([--with-iokit], [Use IOKit instead of libusb on OS X [default=yes]])],
105 | 		[],
106 | 		[with_iokit=yes])
107 | 	]
108 | )
109 | 
110 | AS_IF([test "x$with_dummy" = "xyes"], [
111 | 	AC_DEFINE(USE_DUMMY, 1, [Define if we are using dummy USB driver])
112 | 	USB_BACKEND="dummy"
113 | ], [
114 | 	AS_IF([test "x$with_iokit" = "xyes" && test "x$have_iokit" = "xyes"], [
115 | 		AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit])
116 | 		USB_BACKEND="IOKit"
117 | 	], [
118 | 		AS_IF([test "x$win32" = "xtrue"], [
119 | 			USB_BACKEND="win32 native (setupapi)"
120 | 		], [
121 | 			PKG_CHECK_MODULES(libusb, libusb-1.0 >= $LIBUSB_VERSION)
122 | 			USB_BACKEND="libusb `$PKG_CONFIG --modversion libusb-1.0`"
123 | 			LIBUSB_REQUIRED="libusb-1.0 >= $LIBUSB_VERSION"
124 | 			AC_SUBST(LIBUSB_REQUIRED)
125 | 		])
126 | 	])
127 | ])
128 | 
129 | AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith -Wwrite-strings -Wswitch-default -Wno-unused-parameter -fvisibility=hidden")
130 | 
131 | if test "x$enable_static" = "xyes" -a "x$enable_shared" = "xno"; then
132 | 	GLOBAL_CFLAGS+=" -DIRECV_STATIC"
133 | fi
134 | 
135 | AC_SUBST(GLOBAL_CFLAGS)
136 | AC_SUBST(GLOBAL_LDFLAGS)
137 | 
138 | # check for large file support
139 | AC_SYS_LARGEFILE
140 | 
141 | AC_ARG_WITH([udev],
142 | 	AS_HELP_STRING([--with-udev],
143 | 	[Configure and install udev rules file for DFU/Recovery mode devices]),
144 | 	[],
145 | 	[if $($PKG_CONFIG --exists udev); then with_udev=yes; else with_udev=no; fi])
146 | 
147 | AC_ARG_WITH([udevrulesdir],
148 | 	AS_HELP_STRING([--with-udevrulesdir=DIR],
149 | 	[Directory for udev rules (implies --with-udev)]),
150 | 	[with_udev=yes],
151 | 	[with_udevrulesdir=auto])
152 | 
153 | AC_ARG_WITH([udevrule],
154 | 	AS_HELP_STRING([--with-udevrule="RULE"],
155 | 	[udev activation rule (implies --with-udev)]),
156 | 	[with_udev=yes],
157 | 	[with_udevrule=auto])
158 | 
159 | if test "x$with_udev" = "xyes"; then
160 | 	if test "x$with_udevrule" = "xauto"; then
161 | 		for I in plugdev storage disk staff; do
162 | 			if grep $I /etc/group >/dev/null; then
163 | 				USEGROUP=$I
164 | 				break
165 | 			fi
166 | 		done
167 | 		if test "x$USEGROUP" != "x"; then
168 | 			if ! groups |grep $USEGROUP >/dev/null; then
169 | 				AC_MSG_WARN([The group '$USEGROUP' was determined to be used for the udev rule, but the current user is not member of this group.])
170 | 			fi
171 | 		else
172 | 			AC_MSG_ERROR([Could not determine an appropriate user group for the udev activation rule.
173 |     Please manually specify a udev activation rule using --with-udevrule=<RULE>
174 |     Example: --with-udevrule="OWNER=\\"root\\", GROUP=\\"myusergroup\\", MODE=\\"0660\\""])
175 | 		fi
176 | 		with_udevrule="OWNER=\"root\", GROUP=\"$USEGROUP\", MODE=\"0660\""
177 | 	fi
178 | 
179 | 	if test "x$with_udevrulesdir" = "xauto"; then
180 | 		udevdir=$($PKG_CONFIG --silence-errors --variable=udevdir udev)
181 | 		if test "x$udevdir" != "x"; then
182 | 			with_udevrulesdir=$udevdir"/rules.d"
183 | 		else
184 | 			with_udevrulesdir="\${prefix}/lib/udev/rules.d"
185 | 			AC_MSG_WARN([Could not determine default udev rules directory. Using $with_udevrulesdir.])
186 | 		fi
187 | 	fi
188 | 
189 | 	AC_SUBST([udev_activation_rule], [$with_udevrule])
190 | 	AC_SUBST([udevrulesdir], [$with_udevrulesdir])
191 | fi
192 | AM_CONDITIONAL(WITH_UDEV, test "x$with_udev" = "xyes")
193 | 
194 | m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
195 | 
196 | AC_CONFIG_FILES([
197 | Makefile
198 | src/Makefile
199 | src/libirecovery-1.0.pc
200 | udev/39-libirecovery.rules
201 | include/Makefile
202 | tools/Makefile
203 | udev/Makefile
204 | ])
205 | AC_OUTPUT
206 | 
207 | echo "
208 | Configuration for $PACKAGE $VERSION:
209 | -------------------------------------------
210 | 
211 |   Install prefix: .........: $prefix
212 |   USB backend: ............: $USB_BACKEND
213 |   Build tools: ............: $with_tools
214 | 
215 |   Now type 'make' to build $PACKAGE $VERSION,
216 |   and then 'make install' for installation.
217 | "
218 | 


--------------------------------------------------------------------------------
/git-version-gen:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | SRCDIR=`dirname $0`
 3 | if test -n "$1"; then
 4 |   VER=$1
 5 | else
 6 |   if test -r "${SRCDIR}/.git" && test -x "`which git`" ; then
 7 |     git update-index -q --refresh
 8 |     if ! VER=`git describe --tags --dirty 2>/dev/null`; then
 9 |       COMMIT=`git rev-parse --short HEAD`
10 |       DIRTY=`git diff --quiet HEAD || echo "-dirty"`
11 |       VER=`sed -n '1,/RE/s/Version \(.*\)/\1/p' ${SRCDIR}/NEWS`-git-${COMMIT}${DIRTY}
12 |     fi
13 |   else
14 |     if test -f "${SRCDIR}/.tarball-version"; then
15 |       VER=`cat "${SRCDIR}/.tarball-version"`
16 |     fi
17 |   fi
18 | fi
19 | VER=`printf %s "$VER" | head -n1`
20 | printf %s "$VER"
21 | 


--------------------------------------------------------------------------------
/include/Makefile.am:
--------------------------------------------------------------------------------
1 | nobase_dist_include_HEADERS = libirecovery.h


--------------------------------------------------------------------------------
/include/libirecovery.h:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * libirecovery.h
  3 |  * Communication to iBoot/iBSS on Apple iOS devices via USB
  4 |  *
  5 |  * Copyright (c) 2012-2023 Nikias Bassen <nikias@gmx.li>
  6 |  * Copyright (c) 2012-2013 Martin Szulecki <m.szulecki@libimobiledevice.org>
  7 |  * Copyright (c) 2010 Chronic-Dev Team
  8 |  * Copyright (c) 2010 Joshua Hill
  9 |  *
 10 |  * All rights reserved. This program and the accompanying materials
 11 |  * are made available under the terms of the GNU Lesser General Public License
 12 |  * (LGPL) version 2.1 which accompanies this distribution, and is available at
 13 |  * http://www.gnu.org/licenses/lgpl-2.1.html
 14 |  *
 15 |  * This library is distributed in the hope that it will be useful,
 16 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 18 |  * Lesser General Public License for more details.
 19 |  */
 20 | 
 21 | #ifndef LIBIRECOVERY_H
 22 | #define LIBIRECOVERY_H
 23 | 
 24 | #ifdef __cplusplus
 25 | extern "C" {
 26 | #endif
 27 | 
 28 | #include <stdint.h>
 29 | 
 30 | #ifndef IRECV_API
 31 |   #ifdef IRECV_STATIC
 32 |     #define IRECV_API
 33 |   #elif defined(_WIN32)
 34 |     #define IRECV_API __declspec(dllimport)
 35 |   #else
 36 |     #define IRECV_API
 37 |   #endif
 38 | #endif
 39 | 
 40 | enum irecv_mode {
 41 | 	IRECV_K_RECOVERY_MODE_1   = 0x1280,
 42 | 	IRECV_K_RECOVERY_MODE_2   = 0x1281,
 43 | 	IRECV_K_RECOVERY_MODE_3   = 0x1282,
 44 | 	IRECV_K_RECOVERY_MODE_4   = 0x1283,
 45 | 	IRECV_K_WTF_MODE          = 0x1222,
 46 | 	IRECV_K_DFU_MODE          = 0x1227,
 47 | 	IRECV_K_PORT_DFU_MODE     = 0xf014
 48 | };
 49 | 
 50 | typedef enum {
 51 | 	IRECV_E_SUCCESS           =  0,
 52 | 	IRECV_E_NO_DEVICE         = -1,
 53 | 	IRECV_E_OUT_OF_MEMORY     = -2,
 54 | 	IRECV_E_UNABLE_TO_CONNECT = -3,
 55 | 	IRECV_E_INVALID_INPUT     = -4,
 56 | 	IRECV_E_FILE_NOT_FOUND    = -5,
 57 | 	IRECV_E_USB_UPLOAD        = -6,
 58 | 	IRECV_E_USB_STATUS        = -7,
 59 | 	IRECV_E_USB_INTERFACE     = -8,
 60 | 	IRECV_E_USB_CONFIGURATION = -9,
 61 | 	IRECV_E_PIPE              = -10,
 62 | 	IRECV_E_TIMEOUT           = -11,
 63 | 	IRECV_E_UNSUPPORTED       = -254,
 64 | 	IRECV_E_UNKNOWN_ERROR     = -255
 65 | } irecv_error_t;
 66 | 
 67 | typedef enum {
 68 | 	IRECV_RECEIVED            = 1,
 69 | 	IRECV_PRECOMMAND          = 2,
 70 | 	IRECV_POSTCOMMAND         = 3,
 71 | 	IRECV_CONNECTED           = 4,
 72 | 	IRECV_DISCONNECTED        = 5,
 73 | 	IRECV_PROGRESS            = 6
 74 | } irecv_event_type;
 75 | 
 76 | typedef struct {
 77 | 	int size;
 78 | 	const char* data;
 79 | 	double progress;
 80 | 	irecv_event_type type;
 81 | } irecv_event_t;
 82 | 
 83 | struct irecv_device {
 84 | 	const char* product_type;
 85 | 	const char* hardware_model;
 86 | 	unsigned int board_id;
 87 | 	unsigned int chip_id;
 88 | 	const char* display_name;
 89 | };
 90 | typedef struct irecv_device* irecv_device_t;
 91 | 
 92 | struct irecv_device_info {
 93 | 	unsigned int cpid;
 94 | 	unsigned int cprv;
 95 | 	unsigned int cpfm;
 96 | 	unsigned int scep;
 97 | 	unsigned int bdid;
 98 | 	uint64_t ecid;
 99 | 	unsigned int ibfl;
100 | 	char* srnm;
101 | 	char* imei;
102 | 	char* srtg;
103 | 	char* serial_string;
104 | 	unsigned char* ap_nonce;
105 | 	unsigned int ap_nonce_size;
106 | 	unsigned char* sep_nonce;
107 | 	unsigned int sep_nonce_size;
108 | 	uint16_t pid;
109 | 	unsigned int have_cpid : 1;
110 | 	unsigned int have_cprv : 1;
111 | 	unsigned int have_cpfm : 1;
112 | 	unsigned int have_scep : 1;
113 | 	unsigned int have_bdid : 1;
114 | 	unsigned int have_ecid : 1;
115 | 	unsigned int have_ibfl : 1;
116 | };
117 | 
118 | typedef enum {
119 | 	IRECV_DEVICE_ADD     = 1,
120 | 	IRECV_DEVICE_REMOVE  = 2
121 | } irecv_device_event_type;
122 | 
123 | typedef struct {
124 | 	irecv_device_event_type type;
125 | 	enum irecv_mode mode;
126 | 	struct irecv_device_info *device_info;
127 | } irecv_device_event_t;
128 | 
129 | typedef struct irecv_client_private irecv_client_private;
130 | typedef irecv_client_private* irecv_client_t;
131 | 
132 | enum {
133 | 	IRECV_SEND_OPT_NONE              = 0,
134 | 	IRECV_SEND_OPT_DFU_NOTIFY_FINISH = (1 << 0),
135 | 	IRECV_SEND_OPT_DFU_FORCE_ZLP     = (1 << 1),
136 | 	IRECV_SEND_OPT_DFU_SMALL_PKT     = (1 << 2)
137 | };
138 | 
139 | /* library */
140 | IRECV_API void irecv_set_debug_level(int level);
141 | IRECV_API const char* irecv_strerror(irecv_error_t error);
142 | 
143 | IRECV_API const char* irecv_version();
144 | 
145 | /* device connectivity */
146 | IRECV_API irecv_error_t irecv_open_with_ecid(irecv_client_t* client, uint64_t ecid);
147 | IRECV_API irecv_error_t irecv_open_with_ecid_and_attempts(irecv_client_t* pclient, uint64_t ecid, int attempts);
148 | IRECV_API irecv_error_t irecv_reset(irecv_client_t client);
149 | IRECV_API irecv_error_t irecv_close(irecv_client_t client);
150 | IRECV_API irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause);
151 | 
152 | /* misc */
153 | IRECV_API irecv_error_t irecv_receive(irecv_client_t client);
154 | IRECV_API irecv_error_t irecv_execute_script(irecv_client_t client, const char* script);
155 | IRECV_API irecv_error_t irecv_reset_counters(irecv_client_t client);
156 | IRECV_API irecv_error_t irecv_finish_transfer(irecv_client_t client);
157 | IRECV_API irecv_error_t irecv_trigger_limera1n_exploit(irecv_client_t client);
158 | 
159 | /* usb helpers */
160 | IRECV_API irecv_error_t irecv_usb_set_configuration(irecv_client_t client, int configuration);
161 | IRECV_API irecv_error_t irecv_usb_set_interface(irecv_client_t client, int usb_interface, int usb_alt_interface);
162 | IRECV_API int irecv_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout);
163 | IRECV_API int irecv_usb_bulk_transfer(irecv_client_t client, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout);
164 | IRECV_API int irecv_usb_interrupt_transfer(irecv_client_t client, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout);
165 | 
166 | /* events */
167 | typedef void(*irecv_device_event_cb_t)(const irecv_device_event_t* event, void *user_data);
168 | typedef struct irecv_device_event_context* irecv_device_event_context_t;
169 | IRECV_API irecv_error_t irecv_device_event_subscribe(irecv_device_event_context_t *context, irecv_device_event_cb_t callback, void *user_data);
170 | IRECV_API irecv_error_t irecv_device_event_unsubscribe(irecv_device_event_context_t context);
171 | typedef int(*irecv_event_cb_t)(irecv_client_t client, const irecv_event_t* event);
172 | IRECV_API irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void *user_data);
173 | IRECV_API irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type);
174 | 
175 | /* I/O */
176 | IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, unsigned int options);
177 | IRECV_API irecv_error_t irecv_send_command(irecv_client_t client, const char* command);
178 | IRECV_API irecv_error_t irecv_send_command_breq(irecv_client_t client, const char* command, uint8_t b_request);
179 | IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, unsigned int options);
180 | IRECV_API irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, unsigned long length);
181 | 
182 | /* commands */
183 | IRECV_API irecv_error_t irecv_saveenv(irecv_client_t client);
184 | IRECV_API irecv_error_t irecv_getenv(irecv_client_t client, const char* variable, char** value);
185 | IRECV_API irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value);
186 | IRECV_API irecv_error_t irecv_setenv_np(irecv_client_t client, const char* variable, const char* value);
187 | IRECV_API irecv_error_t irecv_reboot(irecv_client_t client);
188 | IRECV_API irecv_error_t irecv_getret(irecv_client_t client, unsigned int* value);
189 | 
190 | /* device information */
191 | IRECV_API irecv_error_t irecv_get_mode(irecv_client_t client, int* mode);
192 | IRECV_API const struct irecv_device_info* irecv_get_device_info(irecv_client_t client);
193 | 
194 | /* device database queries */
195 | IRECV_API irecv_device_t irecv_devices_get_all(void);
196 | IRECV_API irecv_error_t irecv_devices_get_device_by_client(irecv_client_t client, irecv_device_t* device);
197 | IRECV_API irecv_error_t irecv_devices_get_device_by_product_type(const char* product_type, irecv_device_t* device);
198 | IRECV_API irecv_error_t irecv_devices_get_device_by_hardware_model(const char* hardware_model, irecv_device_t* device);
199 | 
200 | #ifdef __cplusplus
201 | }
202 | #endif
203 | 
204 | #endif
205 | 


--------------------------------------------------------------------------------
/m4/as-compiler-flag.m4:
--------------------------------------------------------------------------------
 1 | dnl as-compiler-flag.m4 0.1.0
 2 | 
 3 | dnl autostars m4 macro for detection of compiler flags
 4 | 
 5 | dnl David Schleef <ds@schleef.org>
 6 | 
 7 | dnl $Id: as-compiler-flag.m4,v 1.1 2005/12/15 23:35:19 ds Exp $
 8 | 
 9 | dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
10 | dnl Tries to compile with the given CFLAGS.
11 | dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
12 | dnl and ACTION-IF-NOT-ACCEPTED otherwise.
13 | 
14 | AC_DEFUN([AS_COMPILER_FLAG],
15 | [
16 |   AC_MSG_CHECKING([to see if compiler understands $1])
17 | 
18 |   save_CFLAGS="$CFLAGS"
19 |   CFLAGS="$CFLAGS $1"
20 | 
21 |   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])], [flag_ok=yes], [flag_ok=no])
22 |   CFLAGS="$save_CFLAGS"
23 | 
24 |   if test "X$flag_ok" = Xyes ; then
25 |     m4_ifvaln([$2],[$2])
26 |     true
27 |   else
28 |     m4_ifvaln([$3],[$3])
29 |     true
30 |   fi
31 |   AC_MSG_RESULT([$flag_ok])
32 | ])
33 | 
34 | dnl AS_COMPILER_FLAGS(VAR, FLAGS)
35 | dnl Tries to compile with the given CFLAGS.
36 | 
37 | AC_DEFUN([AS_COMPILER_FLAGS],
38 | [
39 |   list=$2
40 |   flags_supported=""
41 |   flags_unsupported=""
42 |   AC_MSG_CHECKING([for supported compiler flags])
43 |   for each in $list
44 |   do
45 |     save_CFLAGS="$CFLAGS"
46 |     CFLAGS="$CFLAGS $each"
47 |     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])], [flag_ok=yes], [flag_ok=no])
48 |     CFLAGS="$save_CFLAGS"
49 | 
50 |     if test "X$flag_ok" = Xyes ; then
51 |       flags_supported="$flags_supported $each"
52 |     else
53 |       flags_unsupported="$flags_unsupported $each"
54 |     fi
55 |   done
56 |   AC_MSG_RESULT([$flags_supported])
57 |   if test "X$flags_unsupported" != X ; then
58 |     AC_MSG_WARN([unsupported compiler flags: $flags_unsupported])
59 |   fi
60 |   $1="$1 $flags_supported"
61 | ])
62 | 
63 | 


--------------------------------------------------------------------------------
/src/Makefile.am:
--------------------------------------------------------------------------------
 1 | AM_CPPFLAGS = -I$(top_srcdir)/include
 2 | 
 3 | AM_CFLAGS = \
 4 | 	$(GLOBAL_CFLAGS) \
 5 | 	$(LFS_CFLAGS) \
 6 | 	$(limd_glue_CFLAGS) \
 7 | 	$(libusb_CFLAGS)
 8 | 
 9 | AM_LDFLAGS = \
10 | 	$(GLOBAL_LDFLAGS) \
11 | 	$(limd_glue_LIBS) \
12 | 	$(libusb_LIBS)
13 | 
14 | lib_LTLIBRARIES = libirecovery-1.0.la
15 | libirecovery_1_0_la_CFLAGS = $(AM_CFLAGS)
16 | libirecovery_1_0_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIRECOVERY_SO_VERSION) -no-undefined
17 | libirecovery_1_0_la_SOURCES = libirecovery.c
18 | 
19 | if WIN32
20 | libirecovery_1_0_la_LDFLAGS += -avoid-version
21 | endif
22 | 
23 | pkgconfigdir = $(libdir)/pkgconfig
24 | pkgconfig_DATA = libirecovery-1.0.pc
25 | 


--------------------------------------------------------------------------------
/src/libirecovery-1.0.pc.in:
--------------------------------------------------------------------------------
 1 | prefix=@prefix@
 2 | exec_prefix=@exec_prefix@
 3 | libdir=@libdir@
 4 | includedir=@includedir@
 5 | 
 6 | Name: @PACKAGE_NAME@
 7 | Description: A library to communicate with iBoot/iBSS on iOS devices via USB
 8 | Version: @PACKAGE_VERSION@
 9 | Libs: -L${libdir} -lirecovery-1.0
10 | Cflags: -I${includedir}
11 | Requires.private: libimobiledevice-glue-1.0 >= @LIMD_GLUE_VERSION@ @LIBUSB_REQUIRED@
12 | 


--------------------------------------------------------------------------------
/tools/Makefile.am:
--------------------------------------------------------------------------------
 1 | if BUILD_TOOLS
 2 | AM_CPPFLAGS = -I$(top_srcdir)/include
 3 | 
 4 | AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS)
 5 | AM_LDFLAGS = $(libusb_LIBS)
 6 | 
 7 | bin_PROGRAMS = irecovery
 8 | 
 9 | irecovery_SOURCES = irecovery.c
10 | irecovery_CFLAGS = $(AM_CFLAGS)
11 | irecovery_LDFLAGS = $(AM_LDFLAGS)
12 | if HAVE_READLINE
13 | irecovery_LDFLAGS += -lreadline
14 | endif
15 | irecovery_LDADD = $(top_builddir)/src/libirecovery-1.0.la
16 | endif
17 | 


--------------------------------------------------------------------------------
/tools/irecovery.c:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * irecovery.c
  3 |  * Software frontend for iBoot/iBSS communication with iOS devices
  4 |  *
  5 |  * Copyright (c) 2012-2023 Nikias Bassen <nikias@gmx.li>
  6 |  * Copyright (c) 2012-2015 Martin Szulecki <martin.szulecki@libimobiledevice.org>
  7 |  * Copyright (c) 2010-2011 Chronic-Dev Team
  8 |  * Copyright (c) 2010-2011 Joshua Hill
  9 |  * Copyright (c) 2008-2011 Nicolas Haunold
 10 |  *
 11 |  * All rights reserved. This program and the accompanying materials
 12 |  * are made available under the terms of the GNU Lesser General Public License
 13 |  * (LGPL) version 2.1 which accompanies this distribution, and is available at
 14 |  * http://www.gnu.org/licenses/lgpl-2.1.html
 15 |  *
 16 |  * This library is distributed in the hope that it will be useful,
 17 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 19 |  * Lesser General Public License for more details.
 20 |  */
 21 | 
 22 | #ifdef HAVE_CONFIG_H
 23 | #include "config.h"
 24 | #endif
 25 | 
 26 | #define TOOL_NAME "irecovery"
 27 | 
 28 | #include <stdio.h>
 29 | #include <stdlib.h>
 30 | #include <unistd.h>
 31 | #include <string.h>
 32 | #include <getopt.h>
 33 | #include <inttypes.h>
 34 | #include <ctype.h>
 35 | #include <libirecovery.h>
 36 | #ifdef HAVE_READLINE
 37 | #include <readline/readline.h>
 38 | #include <readline/history.h>
 39 | #else
 40 | #ifndef _WIN32
 41 | #include <termios.h>
 42 | #endif
 43 | #endif
 44 | 
 45 | #ifdef _WIN32
 46 | #include <windows.h>
 47 | #include <conio.h>
 48 | #define sleep(n) Sleep(1000 * n)
 49 | #endif
 50 | 
 51 | #define FILE_HISTORY_PATH ".irecovery"
 52 | #define debug(...) if (verbose) fprintf(stderr, __VA_ARGS__)
 53 | 
 54 | enum {
 55 | 	kNoAction,
 56 | 	kResetDevice,
 57 | 	kStartShell,
 58 | 	kSendCommand,
 59 | 	kSendFile,
 60 | 	kSendExploit,
 61 | 	kSendScript,
 62 | 	kShowMode,
 63 | 	kRebootToNormalMode,
 64 | 	kQueryInfo,
 65 | 	kListDevices
 66 | };
 67 | 
 68 | static unsigned int quit = 0;
 69 | static unsigned int verbose = 0;
 70 | 
 71 | void print_progress_bar(double progress);
 72 | int received_cb(irecv_client_t client, const irecv_event_t* event);
 73 | int progress_cb(irecv_client_t client, const irecv_event_t* event);
 74 | int precommand_cb(irecv_client_t client, const irecv_event_t* event);
 75 | int postcommand_cb(irecv_client_t client, const irecv_event_t* event);
 76 | 
 77 | static void shell_usage()
 78 | {
 79 | 	printf("Usage:\n");
 80 | 	printf("  /upload FILE\t\tsend FILE to device\n");
 81 | 	printf("  /limera1n [FILE]\trun limera1n exploit and send optional payload from FILE\n");
 82 | 	printf("  /deviceinfo\t\tprint device information (ECID, IMEI, etc.)\n");
 83 | 	printf("  /help\t\t\tshow this help\n");
 84 | 	printf("  /exit\t\t\texit interactive shell\n");
 85 | }
 86 | 
 87 | static const char* mode_to_str(int mode)
 88 | {
 89 | 	switch (mode) {
 90 | 		case IRECV_K_RECOVERY_MODE_1:
 91 | 		case IRECV_K_RECOVERY_MODE_2:
 92 | 		case IRECV_K_RECOVERY_MODE_3:
 93 | 		case IRECV_K_RECOVERY_MODE_4:
 94 | 			return "Recovery";
 95 | 			break;
 96 | 		case IRECV_K_DFU_MODE:
 97 | 			return "DFU";
 98 | 			break;
 99 | 		case IRECV_K_PORT_DFU_MODE:
100 | 			return "Port DFU";
101 | 			break;
102 | 		case IRECV_K_WTF_MODE:
103 | 			return "WTF";
104 | 			break;
105 | 		default:
106 | 			return "Unknown";
107 | 			break;
108 | 	}
109 | }
110 | 
111 | static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
112 | {
113 | 	FILE *f;
114 | 	uint64_t size;
115 | 
116 | 	*length = 0;
117 | 
118 | 	f = fopen(filename, "rb");
119 | 	if (!f) {
120 | 		return;
121 | 	}
122 | 
123 | 	fseek(f, 0, SEEK_END);
124 | 	size = ftell(f);
125 | 	rewind(f);
126 | 
127 | 	if (size == 0) {
128 | 		fclose(f);
129 | 		return;
130 | 	}
131 | 
132 | 	*buffer = (char*)malloc(sizeof(char)*(size+1));
133 | 	fread(*buffer, sizeof(char), size, f);
134 | 	fclose(f);
135 | 
136 | 	*length = size;
137 | }
138 | 
139 | static void print_hex(unsigned char *buf, size_t len)
140 | {
141 | 	size_t i;
142 | 	for (i = 0; i < len; i++) {
143 | 		printf("%02x", buf[i]);
144 | 	}
145 | }
146 | 
147 | static void print_device_info(irecv_client_t client)
148 | {
149 | 	int ret, mode;
150 | 	irecv_device_t device = NULL;
151 | 	const struct irecv_device_info *devinfo = irecv_get_device_info(client);
152 | 	if (devinfo) {
153 | 		printf("CPID: 0x%04x\n", devinfo->cpid);
154 | 		printf("CPRV: 0x%02x\n", devinfo->cprv);
155 | 		printf("BDID: 0x%02x\n", devinfo->bdid);
156 | 		printf("ECID: 0x%016" PRIx64 "\n", devinfo->ecid);
157 | 		printf("CPFM: 0x%02x\n", devinfo->cpfm);
158 | 		printf("SCEP: 0x%02x\n", devinfo->scep);
159 | 		printf("IBFL: 0x%02x\n", devinfo->ibfl);
160 | 		printf("SRTG: %s\n", (devinfo->srtg) ? devinfo->srtg : "N/A");
161 | 		printf("SRNM: %s\n", (devinfo->srnm) ? devinfo->srnm : "N/A");
162 | 		printf("IMEI: %s\n", (devinfo->imei) ? devinfo->imei : "N/A");
163 | 		printf("NONC: ");
164 | 		if (devinfo->ap_nonce) {
165 | 			print_hex(devinfo->ap_nonce, devinfo->ap_nonce_size);
166 | 		} else {
167 | 			printf("N/A");
168 | 		}
169 | 		printf("\n");
170 | 		printf("SNON: ");
171 | 		if (devinfo->sep_nonce) {
172 | 			print_hex(devinfo->sep_nonce, devinfo->sep_nonce_size);
173 | 		} else {
174 | 			printf("N/A");
175 | 		}
176 | 		printf("\n");
177 | 		char* p = strstr(devinfo->serial_string, "PWND:[");
178 | 		if (p) {
179 | 			p+=6;
180 | 			char* pend = strchr(p, ']');
181 | 			if (pend) {
182 | 				printf("PWND: %.*s\n", (int)(pend-p), p);
183 | 			}
184 | 		}
185 | 	} else {
186 | 		printf("Could not get device info?!\n");
187 | 	}
188 | 
189 | 	ret = irecv_get_mode(client, &mode);
190 | 	if (ret == IRECV_E_SUCCESS) {
191 | 		switch (devinfo->pid) {
192 | 			case 0x1881:
193 | 				printf("MODE: DFU via Debug USB (KIS)\n");
194 | 				break;
195 | 			default:
196 | 				printf("MODE: %s\n", mode_to_str(mode));
197 | 				break;
198 | 		}
199 | 	}
200 | 
201 | 	irecv_devices_get_device_by_client(client, &device);
202 | 	if (device) {
203 | 		printf("PRODUCT: %s\n", device->product_type);
204 | 		printf("MODEL: %s\n", device->hardware_model);
205 | 		printf("NAME: %s\n", device->display_name);
206 | 	}
207 | }
208 | 
209 | static void print_devices()
210 | {
211 | 	struct irecv_device *devices = irecv_devices_get_all();
212 | 	struct irecv_device *device = NULL;
213 | 	int i = 0;
214 | 
215 | 	for (i = 0; devices[i].product_type != NULL; i++) {
216 | 		device = &devices[i];
217 | 
218 | 		printf("%s %s 0x%02x 0x%04x %s\n", device->product_type, device->hardware_model, device->board_id, device->chip_id, device->display_name);
219 | 	}
220 | }
221 | 
222 | static int _is_breq_command(const char* cmd)
223 | {
224 | 	return (
225 | 		!strcmp(cmd, "go")
226 | 		|| !strcmp(cmd, "bootx")
227 | 		|| !strcmp(cmd, "reboot")
228 | 		|| !strcmp(cmd, "memboot")
229 | 	);
230 | }
231 | 
232 | static void parse_command(irecv_client_t client, unsigned char* command, unsigned int size)
233 | {
234 | 	char* cmd = strdup((char*)command);
235 | 	char* action = strtok(cmd, " ");
236 | 
237 | 	if (!strcmp(cmd, "/exit")) {
238 | 		quit = 1;
239 | 	} else if (!strcmp(cmd, "/help")) {
240 | 		shell_usage();
241 | 	} else if (!strcmp(cmd, "/upload")) {
242 | 		char* filename = strtok(NULL, " ");
243 | 		debug("Uploading file %s\n", filename);
244 | 		if (filename != NULL) {
245 | 			irecv_send_file(client, filename, 0);
246 | 		}
247 | 	} else if (!strcmp(cmd, "/deviceinfo")) {
248 | 		print_device_info(client);
249 | 	} else if (!strcmp(cmd, "/limera1n")) {
250 | 		char* filename = strtok(NULL, " ");
251 | 		debug("Sending limera1n payload %s\n", filename);
252 | 		if (filename != NULL) {
253 | 			irecv_send_file(client, filename, 0);
254 | 		}
255 | 		irecv_trigger_limera1n_exploit(client);
256 | 	} else if (!strcmp(cmd, "/execute")) {
257 | 		char* filename = strtok(NULL, " ");
258 | 		debug("Executing script %s\n", filename);
259 | 		if (filename != NULL) {
260 | 			char* buffer = NULL;
261 | 			uint64_t buffer_length = 0;
262 | 			buffer_read_from_filename(filename, &buffer, &buffer_length);
263 | 			if (buffer) {
264 | 				buffer[buffer_length] = '\0';
265 | 				irecv_execute_script(client, buffer);
266 | 				free(buffer);
267 | 			} else {
268 | 				printf("Could not read file '%s'\n", filename);
269 | 			}
270 | 		}
271 | 	} else {
272 | 		printf("Unsupported command %s. Use /help to get a list of available commands.\n", cmd);
273 | 	}
274 | 
275 | 	free(action);
276 | }
277 | 
278 | static void load_command_history()
279 | {
280 | #ifdef HAVE_READLINE
281 | 	read_history(FILE_HISTORY_PATH);
282 | #endif
283 | }
284 | 
285 | static void append_command_to_history(const char* cmd)
286 | {
287 | #ifdef HAVE_READLINE
288 | 	add_history(cmd);
289 | 	write_history(FILE_HISTORY_PATH);
290 | #endif
291 | }
292 | 
293 | #ifndef HAVE_READLINE
294 | #ifdef _WIN32
295 | #define BS_CC '\b'
296 | #else
297 | #define BS_CC 0x7f
298 | #define getch getchar
299 | #endif
300 | static void get_input(char *buf, int maxlen)
301 | {
302 | 	int len = 0;
303 | 	int c;
304 | 
305 | 	while ((c = getch())) {
306 | 		if ((c == '\r') || (c == '\n')) {
307 | 			break;
308 | 		}
309 | 		if (isprint(c)) {
310 | 			if (len < maxlen-1)
311 | 				buf[len++] = c;
312 | 		} else if (c == BS_CC) {
313 | 			if (len > 0) {
314 | 				fputs("\b \b", stdout);
315 | 				len--;
316 | 			}
317 | 		}
318 | 	}
319 | 	buf[len] = 0;
320 | }
321 | #endif
322 | 
323 | static void init_shell(irecv_client_t client)
324 | {
325 | 	irecv_error_t error = 0;
326 | 	load_command_history();
327 | 	irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
328 | 	irecv_event_subscribe(client, IRECV_RECEIVED, &received_cb, NULL);
329 | 	irecv_event_subscribe(client, IRECV_PRECOMMAND, &precommand_cb, NULL);
330 | 	irecv_event_subscribe(client, IRECV_POSTCOMMAND, &postcommand_cb, NULL);
331 | 	while (!quit) {
332 | 		error = irecv_receive(client);
333 | 		if (error != IRECV_E_SUCCESS) {
334 | 			debug("%s\n", irecv_strerror(error));
335 | 			break;
336 | 		}
337 | #ifdef HAVE_READLINE
338 | 		char* cmd = readline("> ");
339 | #else
340 | 		char cmdbuf[4096];
341 | 		const char* cmd = &cmdbuf[0];
342 | 		printf("> ");
343 | 		fflush(stdout);
344 | 		get_input(cmdbuf, sizeof(cmdbuf));
345 | #endif
346 | 		if (cmd && *cmd) {
347 | 			if (_is_breq_command(cmd)) {
348 | 				error = irecv_send_command_breq(client, cmd, 1);
349 | 			} else {
350 | 				error = irecv_send_command(client, cmd);
351 | 			}
352 | 			if (error != IRECV_E_SUCCESS) {
353 | 				quit = 1;
354 | 			}
355 | 
356 | 			append_command_to_history(cmd);
357 | 		}
358 | #ifdef HAVE_READLINE
359 | 		free(cmd);
360 | #endif
361 | 	}
362 | }
363 | 
364 | int received_cb(irecv_client_t client, const irecv_event_t* event)
365 | {
366 | 	if (event->type == IRECV_RECEIVED) {
367 | 		int i = 0;
368 | 		int size = event->size;
369 | 		const char* data = event->data;
370 | 		for (i = 0; i < size; i++) {
371 | 			printf("%c", data[i]);
372 | 		}
373 | 	}
374 | 
375 | 	return 0;
376 | }
377 | 
378 | int precommand_cb(irecv_client_t client, const irecv_event_t* event)
379 | {
380 | 	if (event->type == IRECV_PRECOMMAND) {
381 | 		if (event->data[0] == '/') {
382 | 			parse_command(client, (unsigned char*)event->data, event->size);
383 | 			return -1;
384 | 		}
385 | 	}
386 | 
387 | 	return 0;
388 | }
389 | 
390 | int postcommand_cb(irecv_client_t client, const irecv_event_t* event)
391 | {
392 | 	char* value = NULL;
393 | 	char* action = NULL;
394 | 	char* command = NULL;
395 | 	char* argument = NULL;
396 | 	irecv_error_t error = IRECV_E_SUCCESS;
397 | 
398 | 	if (event->type == IRECV_POSTCOMMAND) {
399 | 		command = strdup(event->data);
400 | 		action = strtok(command, " ");
401 | 		if (!strcmp(action, "getenv")) {
402 | 			argument = strtok(NULL, " ");
403 | 			error = irecv_getenv(client, argument, &value);
404 | 			if (error != IRECV_E_SUCCESS) {
405 | 				debug("%s\n", irecv_strerror(error));
406 | 				free(command);
407 | 				return error;
408 | 			}
409 | 			printf("%s\n", value);
410 | 			free(value);
411 | 		}
412 | 
413 | 		if (!strcmp(action, "reboot")) {
414 | 			quit = 1;
415 | 		}
416 | 	}
417 | 
418 | 	free(command);
419 | 
420 | 	return 0;
421 | }
422 | 
423 | int progress_cb(irecv_client_t client, const irecv_event_t* event)
424 | {
425 | 	if (event->type == IRECV_PROGRESS) {
426 | 		print_progress_bar(event->progress);
427 | 	}
428 | 
429 | 	return 0;
430 | }
431 | 
432 | void print_progress_bar(double progress)
433 | {
434 | 	int i = 0;
435 | 
436 | 	if (progress < 0) {
437 | 		return;
438 | 	}
439 | 
440 | 	if (progress > 100) {
441 | 		progress = 100;
442 | 	}
443 | 
444 | 	printf("\r[");
445 | 
446 | 	for (i = 0; i < 50; i++) {
447 | 		if (i < progress / 2) {
448 | 			printf("=");
449 | 		} else {
450 | 			printf(" ");
451 | 		}
452 | 	}
453 | 
454 | 	printf("] %3.1f%%", progress);
455 | 
456 | 	fflush(stdout);
457 | 
458 | 	if (progress == 100) {
459 | 		printf("\n");
460 | 	}
461 | }
462 | 
463 | static void print_usage(int argc, char **argv)
464 | {
465 | 	char *name = NULL;
466 | 	name = strrchr(argv[0], '/');
467 | 	printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0]));
468 | 	printf("\n");
469 | 	printf("Interact with an iOS device in DFU or recovery mode.\n");
470 | 	printf("\n");
471 | 	printf("OPTIONS:\n");
472 | 	printf("  -i, --ecid ECID\tconnect to specific device by its ECID\n");
473 | 	printf("  -c, --command CMD\trun CMD on device\n");
474 | 	printf("  -m, --mode\t\tprint current device mode\n");
475 | 	printf("  -f, --file FILE\tsend file to device\n");
476 | 	printf("  -k, --payload FILE\tsend limera1n usb exploit payload from FILE\n");
477 | 	printf("  -r, --reset\t\treset client\n");
478 | 	printf("  -n, --normal\t\treboot device into normal mode (exit recovery loop)\n");
479 | 	printf("  -e, --script FILE\texecutes recovery script from FILE\n");
480 | 	printf("  -s, --shell\t\tstart an interactive shell\n");
481 | 	printf("  -q, --query\t\tquery device info\n");
482 | 	printf("  -a, --devices\t\tlist information for all known devices\n");
483 | 	printf("  -v, --verbose\t\tenable verbose output, repeat for higher verbosity\n");
484 | 	printf("  -h, --help\t\tprints this usage information\n");
485 | 	printf("  -V, --version\t\tprints version information\n");
486 | 	printf("\n");
487 | 	printf("Homepage:    <" PACKAGE_URL ">\n");
488 | 	printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n");
489 | }
490 | 
491 | int main(int argc, char* argv[])
492 | {
493 | 	static struct option longopts[] = {
494 | 		{ "ecid",    required_argument, NULL, 'i' },
495 | 		{ "command", required_argument, NULL, 'c' },
496 | 		{ "mode",    no_argument,       NULL, 'm' },
497 | 		{ "file",    required_argument, NULL, 'f' },
498 | 		{ "payload", required_argument, NULL, 'k' },
499 | 		{ "reset",   no_argument,       NULL, 'r' },
500 | 		{ "normal",  no_argument,       NULL, 'n' },
501 | 		{ "script",  required_argument, NULL, 'e' },
502 | 		{ "shell",   no_argument,       NULL, 's' },
503 | 		{ "query",   no_argument,       NULL, 'q' },
504 | 		{ "devices", no_argument,       NULL, 'a' },
505 | 		{ "verbose", no_argument,       NULL, 'v' },
506 | 		{ "help",    no_argument,       NULL, 'h' },
507 | 		{ "version", no_argument,       NULL, 'V' },
508 | 		{ NULL, 0, NULL, 0 }
509 | 	};
510 | 	int i = 0;
511 | 	int opt = 0;
512 | 	int action = kNoAction;
513 | 	uint64_t ecid = 0;
514 | 	int mode = -1;
515 | 	char* argument = NULL;
516 | 	irecv_error_t error = 0;
517 | 
518 | 	char* buffer = NULL;
519 | 	uint64_t buffer_length = 0;
520 | 
521 | 	if (argc == 1) {
522 | 		print_usage(argc, argv);
523 | 		return 0;
524 | 	}
525 | 
526 | 	while ((opt = getopt_long(argc, argv, "i:vVhrsmnc:f:e:k:qa", longopts, NULL)) > 0) {
527 | 		switch (opt) {
528 | 			case 'i':
529 | 				if (optarg) {
530 | 					char* tail = NULL;
531 | 					ecid = strtoull(optarg, &tail, 0);
532 | 					if (tail && (tail[0] != '\0')) {
533 | 						ecid = 0;
534 | 					}
535 | 					if (ecid == 0) {
536 | 						fprintf(stderr, "ERROR: Could not parse ECID from argument '%s'\n", optarg);
537 | 						return -1;
538 | 					}
539 | 				}
540 | 				break;
541 | 
542 | 			case 'v':
543 | 				verbose += 1;
544 | 				break;
545 | 
546 | 			case 'h':
547 | 				print_usage(argc, argv);
548 | 				return 0;
549 | 
550 | 			case 'm':
551 | 				action = kShowMode;
552 | 				break;
553 | 
554 | 			case 'n':
555 | 				action = kRebootToNormalMode;
556 | 				break;
557 | 
558 | 			case 'r':
559 | 				action = kResetDevice;
560 | 				break;
561 | 
562 | 			case 's':
563 | 				action = kStartShell;
564 | 				break;
565 | 
566 | 			case 'f':
567 | 				action = kSendFile;
568 | 				argument = optarg;
569 | 				break;
570 | 
571 | 			case 'c':
572 | 				action = kSendCommand;
573 | 				argument = optarg;
574 | 				break;
575 | 
576 | 			case 'k':
577 | 				action = kSendExploit;
578 | 				argument = optarg;
579 | 				break;
580 | 
581 | 			case 'e':
582 | 				action = kSendScript;
583 | 				argument = optarg;
584 | 				break;
585 | 
586 | 			case 'q':
587 | 				action = kQueryInfo;
588 | 				break;
589 | 
590 | 			case 'a':
591 | 				action = kListDevices;
592 | 				print_devices();
593 | 				return 0;
594 | 
595 | 			case 'V':
596 | 				printf("%s %s", TOOL_NAME, PACKAGE_VERSION);
597 | #ifdef HAVE_READLINE
598 | 				printf(" (readline)");
599 | #endif
600 | 				printf("\n");
601 | 				return 0;
602 | 
603 | 			default:
604 | 				fprintf(stderr, "Unknown argument\n");
605 | 				return -1;
606 | 		}
607 | 	}
608 | 
609 | 	if (action == kNoAction) {
610 | 		fprintf(stderr, "ERROR: Missing action option\n");
611 | 		print_usage(argc, argv);
612 | 		return -1;
613 | 	}
614 | 
615 | 	if (verbose)
616 | 		irecv_set_debug_level(verbose);
617 | 
618 | 	irecv_client_t client = NULL;
619 | 	for (i = 0; i <= 5; i++) {
620 | 		debug("Attempting to connect... \n");
621 | 
622 | 		irecv_error_t err = irecv_open_with_ecid(&client, ecid);
623 | 		if (err == IRECV_E_UNSUPPORTED) {
624 | 			fprintf(stderr, "ERROR: %s\n", irecv_strerror(err));
625 | 			return -1;
626 | 		}
627 | 		else if (err != IRECV_E_SUCCESS)
628 | 			sleep(1);
629 | 		else
630 | 			break;
631 | 
632 | 		if (i == 5) {
633 | 			fprintf(stderr, "ERROR: %s\n", irecv_strerror(err));
634 | 			return -1;
635 | 		}
636 | 	}
637 | 
638 | 	irecv_device_t device = NULL;
639 | 	irecv_devices_get_device_by_client(client, &device);
640 | 	if (device)
641 | 		debug("Connected to %s, model %s, cpid 0x%04x, bdid 0x%02x\n", device->product_type, device->hardware_model, device->chip_id, device->board_id);
642 | 
643 | 	const struct irecv_device_info *devinfo = irecv_get_device_info(client);
644 | 
645 | 	switch (action) {
646 | 		case kResetDevice:
647 | 			irecv_reset(client);
648 | 			break;
649 | 
650 | 		case kSendFile:
651 | 			irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
652 | 			error = irecv_send_file(client, argument, IRECV_SEND_OPT_DFU_NOTIFY_FINISH);
653 | 			debug("%s\n", irecv_strerror(error));
654 | 			break;
655 | 
656 | 		case kSendCommand:
657 | 			if (devinfo->pid == 0x1881) {
658 | 				printf("Shell is not available in Debug USB (KIS) mode.\n");
659 | 				break;
660 | 			}
661 | 			if (_is_breq_command(argument)) {
662 | 				error = irecv_send_command_breq(client, argument, 1);
663 | 			} else {
664 | 				error = irecv_send_command(client, argument);
665 | 			}
666 | 			debug("%s\n", irecv_strerror(error));
667 | 			break;
668 | 
669 | 		case kSendExploit:
670 | 			if (devinfo->pid == 0x1881) {
671 | 				printf("Shell is not available in Debug USB (KIS) mode.\n");
672 | 				break;
673 | 			}
674 | 			if (argument != NULL) {
675 | 				irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
676 | 				error = irecv_send_file(client, argument, 0);
677 | 				if (error != IRECV_E_SUCCESS) {
678 | 					debug("%s\n", irecv_strerror(error));
679 | 					break;
680 | 				}
681 | 			}
682 | 			error = irecv_trigger_limera1n_exploit(client);
683 | 			debug("%s\n", irecv_strerror(error));
684 | 			break;
685 | 
686 | 		case kStartShell:
687 | 			if (devinfo->pid == 0x1881) {
688 | 				printf("This feature is not supported in Debug USB (KIS) mode.\n");
689 | 				break;
690 | 			}
691 | 			init_shell(client);
692 | 			break;
693 | 
694 | 		case kSendScript:
695 | 			if (devinfo->pid == 0x1881) {
696 | 				printf("This feature is not supported in Debug USB (KIS) mode.\n");
697 | 				break;
698 | 			}
699 | 			buffer_read_from_filename(argument, &buffer, &buffer_length);
700 | 			if (buffer) {
701 | 				buffer[buffer_length] = '\0';
702 | 
703 | 				error = irecv_execute_script(client, buffer);
704 | 				if (error != IRECV_E_SUCCESS) {
705 | 					debug("%s\n", irecv_strerror(error));
706 | 				}
707 | 
708 | 				free(buffer);
709 | 			} else {
710 | 				fprintf(stderr, "Could not read file '%s'\n", argument);
711 | 			}
712 | 			break;
713 | 
714 | 		case kShowMode: {
715 | 			irecv_get_mode(client, &mode);
716 | 			printf("%s Mode", mode_to_str(mode));
717 | 			if (devinfo->pid == 0x1881) {
718 | 				printf(" via Debug USB (KIS)");
719 | 			}
720 | 			printf("\n");
721 | 			break;
722 | 		}
723 | 		case kRebootToNormalMode:
724 | 			if (devinfo->pid == 0x1881) {
725 | 				printf("This feature is not supported in Debug USB (KIS) mode.\n");
726 | 				break;
727 | 			}
728 | 			error = irecv_setenv(client, "auto-boot", "true");
729 | 			if (error != IRECV_E_SUCCESS) {
730 | 				debug("%s\n", irecv_strerror(error));
731 | 				break;
732 | 			}
733 | 
734 | 			error = irecv_saveenv(client);
735 | 			if (error != IRECV_E_SUCCESS) {
736 | 				debug("%s\n", irecv_strerror(error));
737 | 				break;
738 | 			}
739 | 
740 | 			error = irecv_reboot(client);
741 | 			if (error != IRECV_E_SUCCESS) {
742 | 				debug("%s\n", irecv_strerror(error));
743 | 			} else {
744 | 				debug("%s\n", irecv_strerror(error));
745 | 			}
746 | 			break;
747 | 
748 | 		case kQueryInfo:
749 | 			print_device_info(client);
750 | 			break;
751 | 
752 | 		default:
753 | 			fprintf(stderr, "Unknown action\n");
754 | 			break;
755 | 	}
756 | 
757 | 	irecv_close(client);
758 | 
759 | 	return 0;
760 | }
761 | 


--------------------------------------------------------------------------------
/udev/39-libirecovery.rules.in:
--------------------------------------------------------------------------------
1 | # Handle iOS devices in DFU and Recovery mode - for use with libirecovery
2 | 
3 | # Change group and permissions of iOS devices in DFU, legacy WTF, and Recovery mode
4 | ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="05ac", ATTR{idProduct}=="122[27]|128[0-3]", @udev_activation_rule@
5 | 
6 | # Handle checkra1n DFU mode
7 | ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="05ac", ATTR{idProduct}=="1338", @udev_activation_rule@
8 | 
9 | 


--------------------------------------------------------------------------------
/udev/Makefile.am:
--------------------------------------------------------------------------------
 1 | if WITH_UDEV
 2 | edit = \
 3 | 	$(SED) -r \
 4 | 	-e 's|@udev_activation_rule[@]|$(udev_activation_rule)|g' \
 5 | 	< 
lt; > $@ || rm $@
 6 | 
 7 | udevrules_DATA = \
 8 | 	39-libirecovery.rules
 9 | 
10 | 39-libirecovery.rules: 39-libirecovery.rules.in
11 | 	$(edit)
12 | 
13 | EXTRA_DIST = \
14 | 	39-libirecovery.rules.in
15 | 
16 | MAINTAINERCLEANFILES = \
17 | 	39-libirecovery.rules
18 | 
19 | CLEANFILES = \
20 | 	39-libirecovery.rules
21 | endif
22 | 


--------------------------------------------------------------------------------