Showing preview only (1,055K chars total). Download the full file or copy to clipboard to get everything.
Repository: boundarydevices/imx_usb_loader
Branch: master
Commit: 30b43d69770c
Files: 47
Total size: 1023.3 KB
Directory structure:
gitextract_fml__pjx/
├── .gitignore
├── COPYING
├── Makefile
├── Makefile.mingw
├── README.md
├── image.h
├── imx_loader.h
├── imx_loader_config.c
├── imx_loader_config.h
├── imx_sdp.c
├── imx_sdp.h
├── imx_sdp_simulation.c
├── imx_sdp_simulation.h
├── imx_uart.c
├── imx_usb.c
├── imx_usb.conf
├── msvc/
│ ├── getopt.c
│ ├── getopt.h
│ ├── imx_loader.sln
│ ├── imx_uart.vcxproj
│ └── imx_usb.vcxproj
├── mx50_usb_work.conf
├── mx51_usb_work.conf
├── mx53_usb_work.conf
├── mx6_usb_sdp_spl.conf
├── mx6_usb_work.conf
├── mx6ull_usb_work.conf
├── mx7_usb_work.conf
├── mx7ulp_usb_work.conf
├── mx8m_usb_sdp_spl.conf
├── mx8mm_usb_work.conf
├── mx8mn_usb_work.conf
├── mx8mq_usb_work.conf
├── portable.h
├── sdp.c
├── sdp.h
├── sdps.c
├── sdps.h
├── tests/
│ ├── Makefile
│ ├── bare.cfg
│ ├── create.txt
│ ├── dcd.cfg
│ ├── plugin.cfg
│ ├── test-dcd.imx.output
│ ├── test-plugin.imx.output
│ └── test.imx.output
└── vybrid_usb_work.conf
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.o
imx_usb
imx_uart
imx_usb.lds
imx_uart.lds
*.bin
*.imx
.*.swp
tests/*.test
================================================
FILE: COPYING
================================================
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
================================================
FILE: Makefile
================================================
all: imx_usb imx_uart
DESTDIR ?=
prefix ?= /usr
bindir ?= $(prefix)/bin
sysconfdir ?= $(prefix)/etc
rel_sysconfdir = $(shell realpath -m --relative-to=$(bindir) $(sysconfdir))
BUILDHOST := $(shell uname -s)
BUILDHOST := $(patsubst CYGWIN_%,CYGWIN,$(BUILDHOST))
ifneq ($(BUILDHOST),CYGWIN)
PKG_CONFIG ?= pkg-config
USBCFLAGS = `$(PKG_CONFIG) --cflags libusb-1.0`
USBLDFLAGS = `$(PKG_CONFIG) --libs libusb-1.0`
else
USBCFLAGS = -I/usr/include/libusb-1.0
USBLDFLAGS = -L/usr/lib -lusb-1.0
endif
CONFCPPFLAGS = -DSYSCONFDIR='"$(sysconfdir)"' -DREL_SYSCONFDIR='"$(rel_sysconfdir)"'
CFLAGS ?= -Wall -Wstrict-prototypes -Wno-trigraphs
imx_usb.o : imx_usb.c imx_sdp.h imx_loader_config.h portable.h
$(CC) -c $*.c -o $@ -pipe -ggdb $(USBCFLAGS) $(CFLAGS) $(CONFCPPFLAGS)
%.o : %.c imx_sdp.h imx_loader_config.h portable.h image.h
$(CC) -c $*.c -o $@ -pipe -ggdb $(CFLAGS) $(CONFCPPFLAGS)
imx_usb: imx_usb.o imx_sdp.o imx_sdp_simulation.o imx_loader_config.o sdp.o sdps.o
$(CC) -o $@ $^ $(LDFLAGS) $(USBLDFLAGS)
imx_uart: imx_uart.o imx_sdp.o imx_loader_config.o sdp.o
$(CC) -o $@ $^ $(LDFLAGS)
install: imx_usb imx_uart
mkdir -p '$(DESTDIR)$(sysconfdir)/imx-loader.d/'
install -m644 *.conf '$(DESTDIR)$(sysconfdir)/imx-loader.d/'
mkdir -p '$(DESTDIR)$(bindir)'
install -m755 imx_usb '$(DESTDIR)$(bindir)/imx_usb'
install -m755 imx_uart '$(DESTDIR)$(bindir)/imx_uart'
uninstall:
rm -rf '$(DESTDIR)$(sysconfdir)/imx-loader.d/'
rm -rf '$(DESTDIR)$(bindir)/imx_usb'
rm -rf '$(DESTDIR)$(bindir)/imx_uart'
clean:
rm -f imx_usb imx_uart *.o
tests: imx_usb
$(MAKE) -C tests/ tests
regen: imx_usb
$(MAKE) -C tests/ regen
.PHONY: all clean install tests
================================================
FILE: Makefile.mingw
================================================
all: imx_usb imx_uart
#$(foreach v,$(.VARIABLES), $(info $(v) = $($(v))))
# Building with MinGW natively
CC = gcc
USBCFLAGS = -I$(LIBUSBPATH)\include
USBLDFLAGS = -L$(LIBUSBPATH)\MinGW32\dll -lusb-1.0
imx_usb.o : imx_usb.c imx_sdp.h portable.h
$(CC) -c $*.c -o $@ -Wstrict-prototypes -Wno-trigraphs -pipe -ggdb $(USBCFLAGS) $(CFLAGS)
%.o : %.c imx_sdp.h portable.h
$(CC) -c $*.c -o $@ -Wstrict-prototypes -Wno-trigraphs -pipe -ggdb $(CFLAGS)
imx_usb: imx_usb.o imx_sdp.o imx_loader_config.o sdp.o sdps.o imx_sdp_simulation.o
$(CC) -o $@ $@.o imx_sdp.o imx_loader_config.o sdp.o sdps.o imx_sdp_simulation.o $(LDFLAGS) $(USBLDFLAGS)
imx_uart: imx_uart.o imx_sdp.o imx_loader_config.o sdp.o
$(CC) -o $@ $@.o imx_sdp.o imx_loader_config.o sdp.o $(LDFLAGS)
clean:
del /f /q imx_usb imx_uart imx_usb.o imx_uart.o imx_sdp.o
.PHONY: all clean install
================================================
FILE: README.md
================================================
# imx_loader
i.MX/Vybrid recovery utility
## Description
This utility allows to download and execute code on Freescale i.MX5/i.MX6/i.MX7
and Vybrid SoCs through the Serial Download Protocol (SDP). Depending on
the board, there is usually some kind of recovery button to bring the SoC
into serial download boot mode, check documentation of your hardware.
The utility support USB and UART as serial link.
## Installation
1. Clone
1. Make sure libusb (1.0) is available
1. Compile using make
Two binaries are available, imx_usb and imx_uart for the two supported
connections.
### Windows
Two variants have been tested successfully to build imx_usb and imx_uart
on Windows:
1. MinGW (using the Microsoft C runtime)
1. Visual Studio 2015
#### MinGW
MinGW allows to use the GNU toolchain (including GCC) to compile a native
Microsoft Windows application. A MinGW specific make file (Makefile.mingw)
is available which allows to build imx_usb/imx_uart with the native make
port (mingw32-make.exe). After installing MinGW, make sure you have a
compiled copy of libusb available and build imx_loader using:
```
mingw32-make -f Makefile.mingw LIBUSBPATH=C:\path\to\libusb
```
This dynamically links against libusb, hence make sure to ship the
library libusb-1.0.dll along with imx_usb.exe.
#### Visual Studio
The subdirectory msvc/ contains the project files for Visual Studio 2015.
Make sure you have the Visual C++ component installed. There is one solution
containing two projects, one for imx_usb and one for imx_uart. The imx_usb
project requires libusb to be present at ../../libusb (relative to the msvc)
directory. If you use an alternative location or compile libusb from source
too, you will have to alter the include/library path in the project settings.
### macOS
libusb and pkg-config can be installed via Homebrew.
If imx_usb fails to claim interface, com.apple.driver.usb.IOUSBHostHIDDevice
needs to be unloaded so libusb can claim, run:
```
sudo kextunload -b com.apple.driver.usb.IOUSBHostHIDDevice
```
## Usage
Using USB, your device should be detected automatically using the USB
VID/PID from imx_usb.conf. Using UART, the user has to specify a
configuration file. This file is needed to use the correct protocol
variant for the target device (transfer configuration). The
configuration file can also contains work item(s).
Work items can also be defined using the command line. By specifying a
file in the command line, the utility automatically uses this file as
a work item and reads parameter from its header:
```
./imx_usb u-boot.imx
```
However, parameters can also specified manually, e.g.
```
./imx_usb u-boot.imx -l0x3f400400 -s370796 -v
```
The UART link uses hardware flow control using RTS/CTS, so make sure
those are available. The imx_uart utility will configure the target
tty with the right baud rate (115200) and flow control settings:
```
./imx_uart /dev/ttyUSB0 vybrid_usb_work.conf u-boot.imx
```
================================================
FILE: image.h
================================================
/*
* (C) Copyright 2008 Semihalf
*
* (C) Copyright 2000-2005
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
********************************************************************
* NOTE: This header file defines an interface to U-Boot. Including
* this (unmodified) header file in another file is considered normal
* use of U-Boot, and does *not* fall under the heading of "derived
* work".
********************************************************************
*/
#ifndef __IMAGE_H__
#define __IMAGE_H__
#include <stdint.h>
typedef uint32_t __be32;
/*
* Operating System Codes
*
* The following are exposed to uImage header.
* Do not change values for backward compatibility.
*/
enum {
IH_OS_INVALID = 0, /* Invalid OS */
IH_OS_OPENBSD, /* OpenBSD */
IH_OS_NETBSD, /* NetBSD */
IH_OS_FREEBSD, /* FreeBSD */
IH_OS_4_4BSD, /* 4.4BSD */
IH_OS_LINUX, /* Linux */
IH_OS_SVR4, /* SVR4 */
IH_OS_ESIX, /* Esix */
IH_OS_SOLARIS, /* Solaris */
IH_OS_IRIX, /* Irix */
IH_OS_SCO, /* SCO */
IH_OS_DELL, /* Dell */
IH_OS_NCR, /* NCR */
IH_OS_LYNXOS, /* LynxOS */
IH_OS_VXWORKS, /* VxWorks */
IH_OS_PSOS, /* pSOS */
IH_OS_QNX, /* QNX */
IH_OS_U_BOOT, /* Firmware */
IH_OS_RTEMS, /* RTEMS */
IH_OS_ARTOS, /* ARTOS */
IH_OS_UNITY, /* Unity OS */
IH_OS_INTEGRITY, /* INTEGRITY */
IH_OS_OSE, /* OSE */
IH_OS_PLAN9, /* Plan 9 */
IH_OS_OPENRTOS, /* OpenRTOS */
IH_OS_COUNT,
};
/*
* CPU Architecture Codes (supported by Linux)
*
* The following are exposed to uImage header.
* Do not change values for backward compatibility.
*/
enum {
IH_ARCH_INVALID = 0, /* Invalid CPU */
IH_ARCH_ALPHA, /* Alpha */
IH_ARCH_ARM, /* ARM */
IH_ARCH_I386, /* Intel x86 */
IH_ARCH_IA64, /* IA64 */
IH_ARCH_MIPS, /* MIPS */
IH_ARCH_MIPS64, /* MIPS 64 Bit */
IH_ARCH_PPC, /* PowerPC */
IH_ARCH_S390, /* IBM S390 */
IH_ARCH_SH, /* SuperH */
IH_ARCH_SPARC, /* Sparc */
IH_ARCH_SPARC64, /* Sparc 64 Bit */
IH_ARCH_M68K, /* M68K */
IH_ARCH_NIOS, /* Nios-32 */
IH_ARCH_MICROBLAZE, /* MicroBlaze */
IH_ARCH_NIOS2, /* Nios-II */
IH_ARCH_BLACKFIN, /* Blackfin */
IH_ARCH_AVR32, /* AVR32 */
IH_ARCH_ST200, /* STMicroelectronics ST200 */
IH_ARCH_SANDBOX, /* Sandbox architecture (test only) */
IH_ARCH_NDS32, /* ANDES Technology - NDS32 */
IH_ARCH_OPENRISC, /* OpenRISC 1000 */
IH_ARCH_ARM64, /* ARM64 */
IH_ARCH_ARC, /* Synopsys DesignWare ARC */
IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */
IH_ARCH_XTENSA, /* Xtensa */
IH_ARCH_COUNT,
};
/*
* Image Types
*
* "Standalone Programs" are directly runnable in the environment
* provided by U-Boot; it is expected that (if they behave
* well) you can continue to work in U-Boot after return from
* the Standalone Program.
* "OS Kernel Images" are usually images of some Embedded OS which
* will take over control completely. Usually these programs
* will install their own set of exception handlers, device
* drivers, set up the MMU, etc. - this means, that you cannot
* expect to re-enter U-Boot except by resetting the CPU.
* "RAMDisk Images" are more or less just data blocks, and their
* parameters (address, size) are passed to an OS kernel that is
* being started.
* "Multi-File Images" contain several images, typically an OS
* (Linux) kernel image and one or more data images like
* RAMDisks. This construct is useful for instance when you want
* to boot over the network using BOOTP etc., where the boot
* server provides just a single image file, but you want to get
* for instance an OS kernel and a RAMDisk image.
*
* "Multi-File Images" start with a list of image sizes, each
* image size (in bytes) specified by an "uint32_t" in network
* byte order. This list is terminated by an "(uint32_t)0".
* Immediately after the terminating 0 follow the images, one by
* one, all aligned on "uint32_t" boundaries (size rounded up to
* a multiple of 4 bytes - except for the last file).
*
* "Firmware Images" are binary images containing firmware (like
* U-Boot or FPGA images) which usually will be programmed to
* flash memory.
*
* "Script files" are command sequences that will be executed by
* U-Boot's command interpreter; this feature is especially
* useful when you configure U-Boot to use a real shell (hush)
* as command interpreter (=> Shell Scripts).
*
* The following are exposed to uImage header.
* Do not change values for backward compatibility.
*/
enum {
IH_TYPE_INVALID = 0, /* Invalid Image */
IH_TYPE_STANDALONE, /* Standalone Program */
IH_TYPE_KERNEL, /* OS Kernel Image */
IH_TYPE_RAMDISK, /* RAMDisk Image */
IH_TYPE_MULTI, /* Multi-File Image */
IH_TYPE_FIRMWARE, /* Firmware Image */
IH_TYPE_SCRIPT, /* Script file */
IH_TYPE_FILESYSTEM, /* Filesystem Image (any type) */
IH_TYPE_FLATDT, /* Binary Flat Device Tree Blob */
IH_TYPE_KWBIMAGE, /* Kirkwood Boot Image */
IH_TYPE_IMXIMAGE, /* Freescale IMXBoot Image */
IH_TYPE_UBLIMAGE, /* Davinci UBL Image */
IH_TYPE_OMAPIMAGE, /* TI OMAP Config Header Image */
IH_TYPE_AISIMAGE, /* TI Davinci AIS Image */
/* OS Kernel Image, can run from any load address */
IH_TYPE_KERNEL_NOLOAD,
IH_TYPE_PBLIMAGE, /* Freescale PBL Boot Image */
IH_TYPE_MXSIMAGE, /* Freescale MXSBoot Image */
IH_TYPE_GPIMAGE, /* TI Keystone GPHeader Image */
IH_TYPE_ATMELIMAGE, /* ATMEL ROM bootable Image */
IH_TYPE_SOCFPGAIMAGE, /* Altera SOCFPGA Preloader */
IH_TYPE_X86_SETUP, /* x86 setup.bin Image */
IH_TYPE_LPC32XXIMAGE, /* x86 setup.bin Image */
IH_TYPE_LOADABLE, /* A list of typeless images */
IH_TYPE_RKIMAGE, /* Rockchip Boot Image */
IH_TYPE_RKSD, /* Rockchip SD card */
IH_TYPE_RKSPI, /* Rockchip SPI image */
IH_TYPE_ZYNQIMAGE, /* Xilinx Zynq Boot Image */
IH_TYPE_ZYNQMPIMAGE, /* Xilinx ZynqMP Boot Image */
IH_TYPE_FPGA, /* FPGA Image */
IH_TYPE_VYBRIDIMAGE, /* VYBRID .vyb Image */
IH_TYPE_TEE, /* Trusted Execution Environment OS Image */
IH_TYPE_FIRMWARE_IVT, /* Firmware Image with HABv4 IVT */
IH_TYPE_COUNT, /* Number of image types */
};
/*
* Compression Types
*
* The following are exposed to uImage header.
* Do not change values for backward compatibility.
*/
enum {
IH_COMP_NONE = 0, /* No Compression Used */
IH_COMP_GZIP, /* gzip Compression Used */
IH_COMP_BZIP2, /* bzip2 Compression Used */
IH_COMP_LZMA, /* lzma Compression Used */
IH_COMP_LZO, /* lzo Compression Used */
IH_COMP_LZ4, /* lz4 Compression Used */
IH_COMP_COUNT,
};
#define IH_MAGIC 0x27051956 /* Image Magic Number */
#define IH_NMLEN 32 /* Image Name Length */
/* Reused from common.h */
#define ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
/*
* Legacy format image header,
* all data in network byte order (aka natural aka bigendian).
*/
typedef struct image_header {
__be32 ih_magic; /* Image Header Magic Number */
__be32 ih_hcrc; /* Image Header CRC Checksum */
__be32 ih_time; /* Image Creation Timestamp */
__be32 ih_size; /* Image Data Size */
__be32 ih_load; /* Data Load Address */
__be32 ih_ep; /* Entry Point Address */
__be32 ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
#endif /* __IMAGE_H__ */
================================================
FILE: imx_loader.h
================================================
/*
* imx_loader common header file for imx_usb/imx_uart
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __IMX_LOADER_H__
#define __IMX_LOADER_H__
#define IMX_LOADER_VERSION "0.2pre"
#endif /* __IMX_LOADER_H__ */
================================================
FILE: imx_loader_config.c
================================================
/*
* imx_loader_config:
* Configuration file parser for imx_usb/imx_uart loader
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "portable.h"
#include "imx_sdp.h"
#include "image.h"
#include "sdp.h"
#include "sdps.h"
int get_val(const char** pp, int base)
{
int val = 0;
const char *p = *pp;
while (*p==' ') p++;
if (*p=='0') {
p++;
if ((*p=='x')||(*p=='X')) {
p++;
base = 16;
}
}
while (*p) {
char c = *p++;
if ((c >= '0')&&(c <= '9')) {
c -= '0';
} else {
c &= ~('a'-'A');
if ((c >= 'A')&&(c <= 'F')) c -= ('A'-10);
else {
p--;
break;
}
}
if (c >= base) {
printf("Syntax error: %s\n", p-1);
val = -1;
break;
}
val = (val * base) + c;
}
while (*p==' ') p++;
*pp = p;
return val;
}
const char *move_string(char *dest, const char *src, unsigned cnt)
{
unsigned i = 0;
while (i < cnt) {
char c = *src++;
if ((!c) || (c == ' ') || (c == 0x0d) || (c == '\n') ||
(c == '#') || (c == ':') || (c == ',')) {
src--;
break;
}
dest[i++] = c;
}
dest[i] = '\0';
return src;
}
char const *get_base_path(char const *argv0)
{
static char base_path[PATH_MAX];
char *e;
strncpy(base_path, argv0, sizeof(base_path));
e = strrchr(base_path, PATH_SEPARATOR);
#ifdef __unix__
if (!e) {
readlink("/proc/self/exe", base_path,sizeof(base_path));
e = strrchr(base_path, PATH_SEPARATOR);
}
#endif
if (e) {
dbg_printf( "trailing slash == %p:%s\n", e, e);
e[1] = 0;
} else {
dbg_printf( "no trailing slash\n");
}
return base_path;
}
char const *get_global_conf_path(void)
{
#ifdef WIN32
static char conf[PATH_MAX];
static char sep = PATH_SEPARATOR;
const char *subdir = "imx_loader";
char const *progdata = getenv("ProgramData");
strncpy(conf, progdata, sizeof(conf));
strncat(conf, &sep, sizeof(conf));
strncat(conf, subdir, sizeof(conf));
return conf;
#else
char const *global_conf_path = SYSCONFDIR "/imx-loader.d/";
return global_conf_path;
#endif
}
char const *conf_path_ok(char const *conf_path, char const *conf_file)
{
static char conf[PATH_MAX];
static char sep = PATH_SEPARATOR;
strncpy(conf, conf_path, sizeof(conf));
strncat(conf, &sep, sizeof(conf) - strlen(conf) - 1);
strncat(conf, conf_file, sizeof(conf) - strlen(conf) - 1);
if (access(conf, R_OK) != -1) {
printf("config file <%s>\n", conf);
return conf;
}
return NULL;
}
char const *conf_file_name(char const *file, char const *base_path, char const *conf_path)
{
char const *conf;
char path[PATH_MAX];
// First priority, conf path... (either -c, binary or /etc/imx-loader.d/)
dbg_printf("checking with conf_path %s\n", conf_path);
conf = conf_path_ok(conf_path, file);
if (conf != NULL)
return conf;
// Second priority, base path, relative path of binary...
dbg_printf("checking with base_path %s\n", base_path);
conf = conf_path_ok(base_path, file);
if (conf != NULL)
return conf;
// Third priority, working directory...
getcwd(path, PATH_MAX);
dbg_printf("checking with cwd %s\n", path);
conf = conf_path_ok(path, file);
if (conf != NULL)
return conf;
#ifndef WIN32
// Fourth priority, conf path relative to base path...
snprintf(path, sizeof(path), "%s/%s", base_path, REL_SYSCONFDIR "/imx-loader.d");
dbg_printf("checking with rel_base_path %s\n", path);
conf = conf_path_ok(path, file);
if (conf != NULL)
return conf;
#endif
printf("%s not found\n", file);
return NULL;
}
char const *skip(const char *p, char c)
{
while (*p==' ') p++;
if (*p == c) {
p++;
}
while (*p==' ') p++;
return p;
}
int end_of_line(const char *p)
{
while (*p == ' ') p++;
if ((!p[0]) || (*p == '#') || (*p == '\n') || (*p == '\r'))
return 1;
return 0;
}
void parse_mem_work(struct sdp_work *curr, const char *filename, const char *p)
{
struct mem_work *wp;
struct mem_work **link;
struct mem_work w;
unsigned int i;
const char *start = p;
p = skip(p,':');
memset(&w, 0, sizeof(w));
if (strncmp(p, "read", 4) == 0) {
p += 4;
p = skip(p,',');
i = MEM_TYPE_READ;
} else if (strncmp(p, "write", 5) == 0) {
p += 5;
p = skip(p,',');
i = MEM_TYPE_WRITE;
} else if (strncmp(p, "modify", 6) == 0) {
p += 6;
p = skip(p,',');
i = MEM_TYPE_MODIFY;
} else {
printf("%s: syntax error: %s {%s}\n", filename, p, start);
}
w.type = i;
i = 0;
for (;;) {
w.vals[i] = get_val(&p, 16);
if (i >= w.type)
break;
p = skip(p,',');
if ((*p == 0) || (*p == '#')) {
printf("%s: missing argment: %s {%s}\n", filename, p, start);
return;
}
i++;
}
if (!end_of_line(p)) {
printf("%s: syntax error: %s {%s}\n", filename, p, start);
return;
}
wp = (struct mem_work *)malloc(sizeof(struct mem_work));
if (!wp)
return;
link = &curr->mem;
while (*link)
link = &(*link)->next;
*wp = w;
*link = wp;
}
void parse_file_work(struct sdp_work *curr, const char *filename, const char *p)
{
const char *start = p;
p = move_string(curr->filename, p, sizeof(curr->filename) - 1);
p = skip(p,':');
for (;;) {
const char *q = p;
if ((!*p) || (*p == '#') || (*p == '\n') || (*p == 0x0d))
break;
if (strncmp(p, "dcd", 3) == 0) {
p += 3;
p = skip(p,',');
curr->dcd = 1;
}
if (strncmp(p, "clear_dcd", 9) == 0) {
p += 9;
p = skip(p,',');
curr->clear_dcd = 1;
// printf("clear_dcd\n");
}
if (strncmp(p, "clear_boot_data", 15) == 0) {
p += 15;
p = skip(p,',');
curr->clear_boot_data = 1;
// printf("clear_dcd\n");
}
if (strncmp(p, "plug", 4) == 0) {
p += 4;
p = skip(p,',');
curr->plug = 1;
// printf("plug\n");
}
if (strncmp(p, "load", 4) == 0) {
p += 4;
curr->load_addr = get_val(&p, 16);
p = skip(p,',');
}
if (strncmp(p, "size", 4) == 0) {
p += 4;
curr->load_size = get_val(&p, 16);
p = skip(p,',');
}
if (strncmp(p, "skip", 4) == 0) {
p += 4;
curr->load_skip = get_val(&p, 16);
p = skip(p,',');
}
if (strncmp(p, "jump_direct", 11) == 0) {
p += 11;
curr->jump_mode = J_ADDR_DIRECT;
curr->jump_addr = get_val(&p, 16);
p = skip(p,',');
}
if (strncmp(p, "jump", 4) == 0) {
p += 4;
curr->jump_mode = J_ADDR_HEADER;
curr->jump_addr = get_val(&p, 16);
if (strncmp(p, "header2", 7) == 0) {
p += 7;
p = skip(p,',');
curr->jump_mode = J_HEADER2;
} else if (strncmp(p, "header", 6) == 0) {
p += 6;
p = skip(p,',');
curr->jump_mode = J_HEADER;
}
p = skip(p,',');
// printf("jump\n");
}
if (q == p) {
printf("%s: syntax error: %s {%s}\n", filename, p, start);
break;
}
}
}
/*
* #hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat valid ram areas)
*hid,1024,0x10000000,1G,0x00907000,0x31000
*
*/
void parse_transfer_type(struct sdp_dev *usb, const char *filename, const char *p)
{
int i;
if (strncmp(p, "hid", 3) == 0) {
p += 3;
p = skip(p,',');
usb->mode = MODE_HID;
sdp_init_ops(usb);
} else if (strncmp(p, "bulk", 4) == 0) {
p += 4;
p = skip(p,',');
usb->mode = MODE_BULK;
sdp_init_ops(usb);
} else if (strncmp(p, "sdps", 4) == 0) {
p += 4;
p = skip(p,',');
usb->mode = MODE_SDPS;
sdps_init_ops(usb);
} else {
printf("%s: hid/bulk/sdps expected\n", filename);
}
if (strncmp(p, "no-hid-cmd", 10) == 0) {
p += 10;
p = skip(p,',');
usb->no_hid_cmd = 1;
}
if (strncmp(p, "ep1", 3) == 0) {
p += 3;
p = skip(p,',');
usb->use_ep1 = 1;
}
if (strncmp(p, "old_header", 10) == 0) {
p += 10;
p = skip(p,',');
usb->header_type = HDR_MX51;
} else if (strncmp(p, "uboot_header", 12) == 0) {
p += 12;
p = skip(p,',');
usb->header_type = HDR_UBOOT;
} else {
usb->header_type = HDR_MX53;
}
usb->max_transfer = get_val(&p, 10);
p = skip(p,',');
usb->dcd_addr = get_val(&p, 16);
p = skip(p,',');
for (i = 0; i < 8; i++) {
usb->ram[i].start = get_val(&p, 10);
p = skip(p,',');
usb->ram[i].size = get_val(&p, 10);
if ((*p == 'G') || (*p == 'g')) {
usb->ram[i].size <<= 30;
p++;
} else if ((*p == 'M') || (*p == 'm')) {
usb->ram[i].size <<= 20;
p++;
} else if ((*p == 'K') || (*p == 'k')) {
usb->ram[i].size <<= 10;
p++;
}
p = skip(p,',');
if ((*p == '#') || (*p == '\n') || (!*p))
break;
}
}
struct sdp_dev *parse_conf(const char *filename)
{
char line[512];
FILE *xfile;
const char *p;
struct sdp_work *tail = NULL;
struct sdp_work *curr = NULL;
struct sdp_dev *usb = (struct sdp_dev *)malloc(sizeof(struct sdp_dev));
if (!usb)
return NULL;
memset(usb, 0, sizeof(struct sdp_dev));
xfile = fopen(filename, "rb" );
if (!xfile) {
printf("Could not open file: {%s}\n", filename);
free(usb);
return NULL;
}
printf("parse %s\n", filename);
while (fgets(line, sizeof(line), xfile) != NULL) {
p = line;
while (*p==' ') p++;
if (p[0] == '#')
continue;
if (p[0] == 0)
continue;
if (p[0] == '\n')
continue;
if (p[0] == 0x0d)
continue;
if (!usb->name[0]) {
p = move_string(usb->name, p, sizeof(usb->name) - 1);
continue;
}
if (!usb->max_transfer) {
parse_transfer_type(usb, filename, p);
continue;
}
/*
* #file:dcd,plug,load nnn,jump [nnn/header/header2]
*/
if (!curr) {
curr = (struct sdp_work *)malloc(sizeof(struct sdp_work));
if (!curr)
break;
memset(curr, 0, sizeof(struct sdp_work));
if (!usb->work)
usb->work = curr;
if (tail)
tail->next = curr;
tail = curr;
}
if (p[0] == ':') {
parse_mem_work(curr, filename, p);
} else {
parse_file_work(curr, filename, p);
curr = NULL;
}
}
return usb;
}
struct sdp_work *parse_cmd_args(int argc, char * const *argv)
{
int i = 0;
struct sdp_work *prev = NULL;
struct sdp_work *w = NULL;
struct sdp_work *head = NULL;
while (argc > i) {
const char *p = argv[i];
if (*p == '-') {
char c;
p++;
c = *p++;
if (w == NULL) {
printf("specify file first\n");
exit(1);
}
if (!*p) {
i++;
p = argv[i];
}
if (c == 's') {
w->load_size = get_val(&p, 10);
if (!w->load_addr)
w->load_addr = 0x10800000;
w->plug = 0;
w->jump_mode = 0;
i++;
continue;
}
if (c == 'l') {
w->load_addr = get_val(&p, 16);
w->plug = 0;
w->jump_mode = 0;
i++;
continue;
}
fprintf(stderr, "Unknown option %s\n", p);
exit(1);
}
// Initialize work structure..
w = malloc(sizeof(struct sdp_work));
memset(w, 0, sizeof(struct sdp_work));
strncpy(w->filename, argv[i], sizeof(w->filename) - 1);
if (access(w->filename, R_OK) == -1) {
fprintf(stderr, "cannot read from file %s\n",
w->filename);
exit(1);
}
if (head == NULL) {
// Special settings for first work...
w->dcd = 1;
w->plug = 1;
w->jump_mode = J_HEADER;
head = w;
}
if (prev != NULL)
prev->next = w;
prev = w;
i++;
}
return head;
}
================================================
FILE: imx_loader_config.h
================================================
/*
* imx_loader_config:
* Configuration file parser for imx_usb/imx_uart loader
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __IMX_LOADER_CONFIG_H__
#define __IMX_LOADER_CONFIG_H__
struct sdp_work;
int get_val(const char** pp, int base);
const char *move_string(char *dest, const char *src, unsigned cnt);
char const *get_global_conf_path(void);
char const *get_base_path(char const *argv0);
char const *conf_file_name(char const *file, char const *base_path, char const *conf_path);
struct sdp_dev *parse_conf(const char *filename);
struct sdp_work *parse_cmd_args(int argc, char * const *argv);
#endif /* __IMX_LOADER_CONFIG_H__ */
================================================
FILE: imx_sdp.c
================================================
/*
* imx_sdp:
* Implementation of the Serial Download Protocol (SDP) for i.MX/Vybrid
* series processors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "portable.h"
#include "imx_sdp.h"
#include "image.h"
#define FT_APP 0xaa
#define FT_CSF 0xcc
#define FT_DCD 0xee
#define FT_LOAD_ONLY 0x00
int debugmode = 0;
#define get_min(a, b) (((a) < (b)) ? (a) : (b))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#ifndef offsetof
#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
//#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
struct load_desc {
struct sdp_work *curr;
FILE* xfile;
unsigned fsize;
int verify;
unsigned char *buf_start;
unsigned buf_size;
unsigned buf_cnt;
unsigned buf_offset;
unsigned dladdr;
unsigned max_length;
unsigned plugin;
unsigned header_addr;
unsigned header_offset;
unsigned char writeable_header[1024];
};
/* Boot data image indicator */
#define PLUGIN_IMAGE_FLAG_MASK (0x0001) /* bit 0 is plugin */
#define HDMI_IMAGE_FLAG_MASK (0x0002) /* bit 1 is HDMI */
struct boot_data {
uint32_t dest;
uint32_t image_len;
uint32_t plugin;
};
/* Command tags and parameters */
#define IVT_HEADER_TAG 0xD1
#define IVT_VERSION 0x40
#define IVT_VERSION_IMX8M 0x41
#define DCD_HEADER_TAG 0xD2
#define DCD_VERSION 0x40
#define DCD_VERSION_IMX8M 0x41
#pragma pack (1)
struct ivt_header {
uint8_t tag;
uint16_t length;
uint8_t version;
};
#pragma pack ()
struct flash_header_v2 {
struct ivt_header header;
uint32_t start_addr;
uint32_t reserv1;
uint32_t dcd_ptr;
uint32_t boot_data_ptr; /* struct boot_data * */
uint32_t self_ptr; /* struct flash_header_v2 *, this - boot_data.start = offset linked at */
uint32_t app_code_csf;
uint32_t reserv2;
};
#pragma pack (1)
struct write_dcd_command {
uint8_t tag;
uint16_t length;
uint8_t param;
};
#pragma pack ()
struct dcd_v2 {
struct ivt_header header;
struct write_dcd_command write_dcd_command;
unsigned char *addr_data;
};
/*
* MX51 header type
*/
struct flash_header_v1 {
uint32_t app_start_addr;
#define APP_BARKER 0xb1
#define DCD_BARKER 0xb17219e9
uint32_t app_barker;
uint32_t csf_ptr;
uint32_t dcd_ptr_ptr;
uint32_t srk_ptr;
uint32_t dcd_ptr;
uint32_t app_dest_ptr;
};
static void print_sdp_work(struct sdp_work *curr)
{
printf("== work item\n");
printf("filename %s\n", curr->filename);
printf("load_size %d bytes\n", curr->load_size);
printf("load_addr 0x%08x\n", curr->load_addr);
printf("dcd %u\n", curr->dcd);
printf("clear_dcd %u\n", curr->clear_dcd);
printf("plug %u\n", curr->plug);
printf("jump_mode %d\n", curr->jump_mode);
printf("jump_addr 0x%08x\n", curr->jump_addr);
printf("== end work item\n");
return;
}
static long get_file_size(FILE *xfile)
{
long size;
fseek(xfile, 0, SEEK_END);
size = ftell(xfile);
rewind(xfile);
// printf("filesize=%lx\n", size);
return size;
}
static int do_response(struct sdp_dev *dev, int report, unsigned int *result,
bool silent)
{
unsigned char tmp[64] = { 0 };
int last_trans, err;
err = dev->ops->transfer(dev, report, tmp, sizeof(tmp), 4, &last_trans);
if ((!silent && err) || debugmode)
printf("report %d in err=%i, last_trans=%i %02x %02x %02x %02x\n",
report, err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
/* At least 4 bytes required for a valid result */
if (last_trans < 4)
return -1;
/*
* Most results are symetric, but likely are meant to be big endian
* as everything else is...
*/
*result = BE32(*((unsigned int*)tmp));
return err;
}
static int do_command(struct sdp_dev *dev, unsigned char *cmd, int cmd_size, int retry)
{
int last_trans, err = -4;
dbg_printf("sending command cmd=%02x %02x %02x %02x\n", cmd[0], cmd[1],cmd[2],cmd[3]);
while (retry) {
err = dev->ops->transfer(dev, 1, (unsigned char *)cmd,
cmd_size, 0, &last_trans);
if (err || debugmode)
printf("%s err=%i, last_trans=%i\n", __func__, err, last_trans);
if (!err)
return 0;
retry--;
}
return err;
}
static int read_memory(struct sdp_dev *dev, unsigned addr, unsigned char *dest, unsigned cnt)
{
unsigned char buf[MAX_PROTOCOL_SIZE];
int cmd_size;
int retry = 0;
int last_trans;
int err;
int rem;
unsigned char tmp[64];
unsigned int sec;
if (!dev->ops->fill_read_reg)
return 0;
cmd_size = dev->ops->fill_read_reg(buf, addr, cnt);
if (cmd_size <= 0)
return cmd_size;
dbg_printf("%s: addr=%08x, cnt=%08x\n", __func__, addr, cnt);
err = do_command(dev, buf, cmd_size, 5);
if (err)
return err;
err = do_response(dev, 3, &sec, false);
if (err)
return err;
rem = cnt;
retry = 0;
while (rem) {
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
err = dev->ops->transfer(dev, 4, tmp, 64, rem > 64 ? 64 : rem, &last_trans);
if (err) {
printf("r4 in err=%i, last_trans=%i %02x %02x %02x %02x cnt=%d rem=%d\n", err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem);
if (retry++ > 8)
break;
continue;
}
retry = 0;
if ((last_trans > rem) || (last_trans > 64)) {
if ((last_trans == 64) && (cnt == rem)) {
/* Last transfer is expected to be too large for HID */
} else {
printf("err: %02x %02x %02x %02x cnt=%d rem=%d last_trans=%i\n", tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem, last_trans);
}
last_trans = rem;
if (last_trans > 64)
last_trans = 64;
}
memcpy(dest, tmp, last_trans);
dest += last_trans;
rem -= last_trans;
}
dbg_printf("%s: %d addr=%08x, val=%02x %02x %02x %02x\n", __func__, err, addr, dest[0], dest[1], dest[2], dest[3]);
return err;
}
static int write_memory(struct sdp_dev *dev, unsigned addr, unsigned val)
{
unsigned char buf[MAX_PROTOCOL_SIZE];
int cmd_size;
int last_trans;
int err = 0;
unsigned char tmp[64] = { 0 };
unsigned int sec;
if (!dev->ops->fill_write_reg)
return 0;
cmd_size = dev->ops->fill_write_reg(buf, addr, val);
if (cmd_size <= 0)
return cmd_size;
dbg_printf("%s: addr=%08x, val=%08x\n", __func__, addr, val);
err = do_command(dev, buf, cmd_size, 5);
if (err)
return err;
err = do_response(dev, 3, &sec, false);
if (err)
return err;
err = dev->ops->transfer(dev, 4, tmp, sizeof(tmp), 4, &last_trans);
dbg_printf("report 4, err=%i, last_trans=%i %02x %02x %02x %02x %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3],
tmp[4], tmp[5], tmp[6], tmp[7]);
if (err)
printf("w4 in err=%i, last_trans=%i %02x %02x %02x %02x\n", err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
return err;
}
static void perform_mem_work(struct sdp_dev *dev, struct mem_work *mem)
{
unsigned tmp, tmp2;
while (mem) {
switch (mem->type) {
case MEM_TYPE_READ:
read_memory(dev, mem->vals[0], (unsigned char *)&tmp, 4);
printf("*%x is %x\n", mem->vals[0], tmp);
break;
case MEM_TYPE_WRITE:
write_memory(dev, mem->vals[0], mem->vals[1]);
printf("%x write %x\n", mem->vals[0], mem->vals[1]);
break;
case MEM_TYPE_MODIFY:
read_memory(dev, mem->vals[0], (unsigned char *)&tmp, 4);
tmp2 = (tmp & ~mem->vals[1]) | mem->vals[2];
printf("%x = %x to %x\n", mem->vals[0], tmp, tmp2);
write_memory(dev, mem->vals[0], tmp2);
break;
}
mem = mem->next;
}
}
static int do_status(struct sdp_dev *dev)
{
unsigned char buf[MAX_PROTOCOL_SIZE];
int cmd_size;
unsigned int hab_security, status;
int retry = 0;
int err;
if (!dev->ops->fill_status)
return 0;
cmd_size = dev->ops->fill_status(buf);
if (cmd_size <= 0)
return cmd_size;
err = do_command(dev, buf, cmd_size, 5);
if (err)
return err;
while (retry < 5) {
err = do_response(dev, 3, &hab_security, false);
if (!err)
break;
retry++;
}
if (err)
return err;
printf("HAB security state: %s (0x%08x)\n", hab_security == HAB_SECMODE_PROD ?
"production mode" : "development mode", hab_security);
if (dev->mode == MODE_HID) {
err = do_response(dev, 4, &status, false);
if (err)
return err;
}
return 0;
}
static int do_data_transfer(struct sdp_dev *dev, unsigned char *buf, int len)
{
int err;
int retry = 10;
int max = dev->max_transfer;
int last_trans;
int cnt;
int transferSize = 0;
while (retry) {
cnt = get_min(len, max);
err = dev->ops->transfer(dev, 2, buf, cnt, 0, &last_trans);
if (!err) {
if (cnt > last_trans)
cnt = last_trans;
if (!cnt) {
printf("Nothing transferred, err=%i transferSize=%i\n", err, transferSize);
return -EIO;
}
transferSize += cnt;
buf += cnt;
len -= cnt;
if (!len)
return transferSize;
retry = 10;
max = dev->max_transfer;
continue;
}
printf("report 2 out err=%i, last_trans=%i len=0x%x max=0x%x retry=%i\n",
err, last_trans, len, max, retry);
if (max >= 16) {
max >>= 1;
max &= ~0x03;
} else {
max <<= 1;
}
/* Wait a few ms before retrying transfer */
msleep(10);
retry--;
}
printf("Giving up\n");
return err;
}
static int write_dcd(struct sdp_dev *dev, struct dcd_v2 *dcd)
{
unsigned char buf[MAX_PROTOCOL_SIZE];
int cmd_size;
int length = BE16(dcd->header.length);
int err;
unsigned transferSize=0;
if (length > HAB_MAX_DCD_SIZE) {
printf("DCD is too big (%d bytes)\n", length);
return -1;
}
if (!dev->ops->fill_dl_dcd)
return 0;
cmd_size = dev->ops->fill_dl_dcd(buf, dev->dcd_addr, length);
if (cmd_size <= 0)
return cmd_size;
printf("loading DCD table @%#x\n", dev->dcd_addr);
err = do_command(dev, buf, cmd_size, 5);
if (err)
return err;
err = do_data_transfer(dev, (unsigned char *)dcd, length);
if (err < 0)
return err;
transferSize = err;
printf("\n<<<%i, %i bytes>>>\n", length, transferSize);
if (dev->mode == MODE_HID) {
unsigned int sec, status;
err = do_response(dev, 3, &sec, false);
if (err)
return err;
err = do_response(dev, 4, &status, false);
if (err)
return err;
if (status == 0x128a8a12UL)
printf("succeeded");
else
printf("failed");
printf(" (security 0x%08x, status 0x%08x)\n", sec, status);
} else {
do_status(dev);
}
return transferSize;
}
static int write_dcd_table_ivt(struct sdp_dev *dev, struct dcd_v2 *dcdhdr)
{
int length = BE16(dcdhdr->header.length);
unsigned char *dcd = (unsigned char *)&dcdhdr->write_dcd_command;
unsigned char *dcd_end;
int err = 0;
printf("main dcd length %x\n", length);
dcd_end = ((unsigned char *)dcdhdr) + length;
while (dcd < dcd_end) {
unsigned s_length = (dcd[1] << 8) + dcd[2];
unsigned sub_tag = (dcd[0] << 24) + (dcd[3] & 0x7);
unsigned flags = (dcd[3] & 0xf8);
unsigned char *s_end = dcd + s_length;
printf("sub dcd length %x\n", s_length);
switch(sub_tag) {
/* Write Data Command */
case 0xcc000004:
if (flags & 0xe8) {
printf("error: Write Data Command with unsupported flags, flags %x.\n", flags);
return -1;
}
dcd += 4;
if (s_end > dcd_end) {
printf("error s_end(%p) > dcd_end(%p)\n", s_end, dcd_end);
return -1;
}
while (dcd < s_end) {
unsigned addr = (dcd[0] << 24) + (dcd[1] << 16) + (dcd[2] << 8) + dcd[3];
unsigned val = (dcd[4] << 24) + (dcd[5] << 16) + (dcd[6] << 8) + dcd[7];
dcd += 8;
dbg_printf("write data *0x%08x = 0x%08x\n", addr, val);
err = write_memory(dev, addr, val);
if (err < 0)
return err;
}
break;
/* Check Data Command */
case 0xcf000004: {
unsigned addr, count, mask, val;
dcd += 4;
addr = (dcd[0] << 24) + (dcd[1] << 16) + (dcd[2] << 8) + dcd[3];
mask = (dcd[4] << 24) + (dcd[5] << 16) + (dcd[6] << 8) + dcd[7];
count = 10000;
switch (s_length) {
case 12:
dcd += 8;
break;
case 16:
count = (dcd[8] << 24) + (dcd[9] << 16) + (dcd[10] << 8) + dcd[11];
dcd += 12;
break;
default:
printf("error s_end(%p) > dcd_end(%p)\n", s_end, dcd_end);
return -1;
}
dbg_printf("Check Data Command, at addr %x, mask %x\n",addr, mask);
while (count) {
val = 0;
err = read_memory(dev, addr, (unsigned char*)&val, 4);
if (err < 0) {
printf("Check Data Command(%x) error(%d) @%x=%x mask %x\n", flags, err, addr, val, mask);
return err;
}
if ((flags == 0x00) && ((val & mask) == 0) )
break;
else if ((flags == 0x08) && ((val & mask) != mask) )
break;
else if ((flags == 0x10) && ((val & mask) == mask) )
break;
else if ((flags == 0x18) && ((val & mask) != 0) )
break;
else if (flags & 0xe0) {
printf("error: Check Data Command with unsupported flags, flags %x.\n", flags);
return -1;
}
count--;
}
if (!count)
printf("!!!Check Data Command(%x) expired without condition met @%x=%x mask %x\n", flags, addr, val, mask);
else
printf("Check Data Command(%x) success @%x=%x mask %x\n", flags, addr, val, mask);
break;
}
default:
printf("Unknown sub tag, dcd[0] 0x%2x, dcd[3] 0x%2x\n", dcd[0], dcd[3]);
return -1;
}
}
return err;
}
static int get_dcd_range_old(struct flash_header_v1 *hdr,
unsigned char *file_start, unsigned cnt,
unsigned char **pstart, unsigned char **pend)
{
unsigned char *dcd_end;
unsigned m_length;
#define cvt_dest_to_src_old (((unsigned char *)&hdr->dcd_ptr) - hdr->dcd_ptr_ptr)
unsigned char* dcd;
unsigned val;
unsigned char* file_end = file_start + cnt;
if (!hdr->dcd_ptr) {
printf("No dcd table, barker=%x\n", hdr->app_barker);
*pstart = *pend = ((unsigned char *)hdr) + sizeof(struct flash_header_v1);
return 0; //nothing to do
}
dcd = hdr->dcd_ptr + cvt_dest_to_src_old;
if ((dcd < file_start) || ((dcd + 8) > file_end)) {
printf("bad dcd_ptr %08x\n", hdr->dcd_ptr);
return -1;
}
val = (dcd[0] << 0) + (dcd[1] << 8) + (dcd[2] << 16) + (dcd[3] << 24);
if (val != DCD_BARKER) {
printf("Unknown tag\n");
return -1;
}
dcd += 4;
m_length = (dcd[0] << 0) + (dcd[1] << 8) + (dcd[2] << 16) + (dcd[3] << 24);
printf("main dcd length %x\n", m_length);
dcd += 4;
dcd_end = dcd + m_length;
if (dcd_end > file_end) {
printf("bad dcd length %08x\n", m_length);
return -1;
}
*pstart = dcd;
*pend = dcd_end;
return 0;
}
static int write_dcd_table_old(struct sdp_dev *dev, struct flash_header_v1 *hdr, unsigned char *file_start, unsigned cnt)
{
unsigned val;
unsigned char *dcd_end;
unsigned char* dcd;
int err = get_dcd_range_old(hdr, file_start, cnt, &dcd, &dcd_end);
if (err < 0)
return err;
while (dcd < dcd_end) {
unsigned type = (dcd[0] << 0) + (dcd[1] << 8) + (dcd[2] << 16) + (dcd[3] << 24);
unsigned addr = (dcd[4] << 0) + (dcd[5] << 8) + (dcd[6] << 16) + (dcd[7] << 24);
val = (dcd[8] << 0) + (dcd[9] << 8) + (dcd[10] << 16) + (dcd[11] << 24);
dcd += 12;
if (type!=4) {
printf("!!!unknown type=%08x *0x%08x = 0x%08x\n", type, addr, val);
} else {
printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val);
err = write_memory(dev, addr, val);
if (err < 0)
return err;
}
}
return err;
}
static void diff_long(unsigned char *src1, unsigned char *src2, unsigned cnt, unsigned skip)
{
unsigned char buf[8*9 + 2];
unsigned *s1 = (unsigned *)src1;
unsigned *s2 = (unsigned *)src2;
unsigned i, j;
while (cnt >= 4) {
unsigned char *p = buf;
unsigned max = get_min(cnt >> 2, 8);
for (i = 0; i < (skip >> 2); i++) {
for (j=0; j < 9; j++)
*p++ = ' ';
}
for (; i < max; i++) {
unsigned s1v = *s1++;
unsigned diff = s1v ^ *s2++;
unsigned c;
*p++ = ' ';
if (i == 4)
*p++ = ' ';
for (j = 0; j < 8; j++) {
unsigned changed = diff & 0xf0000000;
c = ' ';
if (changed) {
if ((s1v & changed) == 0)
c = '^';
else if ((s1v & changed) == changed)
c = 'v';
else
c = '-';
}
*p++ = c;
diff <<= 4;
s1v <<= 4;
}
}
*p = 0;
printf(" %s\n", buf);
cnt -= max << 2;
}
}
void dump_long(unsigned char *src, unsigned cnt, unsigned addr, unsigned skip)
{
unsigned *p = (unsigned *)src;
int i = skip >> 2;
while (cnt >= 4) {
printf("%08x:", addr);
while (skip >= 4) {
printf(" ");
skip -= 4;
}
while (cnt >= 4) {
printf((i==4) ? " %08x":" %08x", p[0]);
p++;
cnt -= 4;
addr += 4;
i++;
if (i==8)
break;
}
printf("\n");
i = 0;
}
}
void dump_bytes(unsigned char *src, unsigned cnt, unsigned addr)
{
unsigned char *p = src;
int i;
while (cnt >= 16) {
printf("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", addr,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
p += 16;
cnt -= 16;
addr += 16;
}
if (cnt) {
printf("%08x:", addr);
i = 0;
while (cnt) {
printf(" %02x", p[0]);
p++;
cnt--;
i++;
if (cnt) if (i == 4) {
i = 0;
printf(" ");
}
}
printf("\n");
}
}
static void fetch_data(struct load_desc *ld, unsigned foffset, unsigned char **p, unsigned *cnt)
{
unsigned skip = foffset - ld->header_offset;
unsigned buf_cnt = ld->buf_cnt;
if ((ld->curr->jump_mode >= J_ADDR_HEADER) &&
(skip < sizeof(ld->writeable_header))) {
*p = &ld->writeable_header[skip];
*cnt = sizeof(ld->writeable_header) - skip;
return;
}
skip = foffset - ld->buf_offset;
if (skip >= buf_cnt) {
fseek(ld->xfile, foffset, SEEK_SET);
ld->buf_offset = foffset;
buf_cnt = ld->buf_cnt = fread(ld->buf_start, 1, ld->buf_size, ld->xfile);
skip = 0;
}
if ((foffset < ld->header_offset) &&
(ld->header_offset < ld->buf_offset + buf_cnt))
buf_cnt = ld->header_offset - ld->buf_offset;
*p = &ld->buf_start[skip];
*cnt = buf_cnt - skip;
}
static int verify_memory(struct sdp_dev *dev, struct load_desc *ld, unsigned foffset,
unsigned size)
{
int mismatch = 0;
unsigned verified = 0;
unsigned total = size;
unsigned addr = ld->dladdr;
while (size) {
unsigned char *p;
unsigned cnt;
unsigned char mem_buf[64];
int align_cnt = foffset & 0x3f;
unsigned offset = foffset;
fetch_data(ld, foffset, &p, &cnt);
if (align_cnt) {
align_cnt = 64 - align_cnt;
if (cnt > align_cnt)
cnt = align_cnt;
}
if (cnt <= 0) {
printf("Unexpected end of file, size=0x%x, cnt=%i\n", size, cnt);
return -1;
}
if (cnt > size)
cnt = size;
size -= cnt;
foffset += cnt;
while (cnt) {
int ret;
unsigned request = get_min(cnt, sizeof(mem_buf));
ret = read_memory(dev, addr, mem_buf, request);
if (ret < 0) {
printf("verified 0x%x of 0x%x before usb error\n", verified, total);
return ret;
}
if (memcmp(p, mem_buf, request)) {
unsigned char * m = mem_buf;
if (!mismatch)
printf("!!!!mismatch\n");
mismatch++;
while (request) {
unsigned skip = addr & 0x1f;
unsigned max = 0x20 - skip;
unsigned req = get_min(request, (int)max);
if (memcmp(p, m, req)) {
dump_long(p, req, offset, skip);
dump_long(m, req, addr, skip);
diff_long(p, m, req, skip);
}
p += req;
m+= req;
offset += req;
addr += req;
cnt -= req;
request -= req;
}
if (mismatch >= 5)
return -1;
}
p += request;
offset += request;
addr += request;
cnt -= request;
verified += request;
}
}
if (!mismatch)
printf("Verify success\n");
return mismatch ? -1 : 0;
}
static int load_file(struct sdp_dev *dev, struct load_desc *ld, unsigned foffset,
unsigned fsize, unsigned char type)
{
unsigned char buf[MAX_PROTOCOL_SIZE];
int cmd_size;
int err;
unsigned transferSize=0;
unsigned char *p;
unsigned cnt;
unsigned char combine_buf[1024];
if (!dev->no_hid_cmd) {
if (!dev->ops->fill_write_file)
return 0;
cmd_size = dev->ops->fill_write_file(buf, ld->dladdr, fsize, type);
if (cmd_size <= 0)
return cmd_size;
dbg_printf("%s:cmd_size=%x\n", __func__, cmd_size);
dbg_dump_long(buf, cmd_size, 0, 0);
do_command(dev, buf, cmd_size, 5);
}
if (dev->mode == MODE_BULK) {
unsigned int sec;
err = do_response(dev, 3, &sec, false);
if (err)
return err;
}
while (transferSize < fsize) {
unsigned remaining = (fsize-transferSize);
fetch_data(ld, foffset, &p, &cnt);
/* Avoid short packets, they may signal end of transfer */
if (cnt < sizeof(combine_buf)) {
unsigned next_cnt;
memcpy(combine_buf, p, cnt);
while (cnt < sizeof(combine_buf)) {
fetch_data(ld, foffset + cnt, &p, &next_cnt);
if (!next_cnt)
break;
if (next_cnt > sizeof(combine_buf) - cnt)
next_cnt = sizeof(combine_buf) - cnt;
memcpy(&combine_buf[cnt], p, next_cnt);
cnt += next_cnt;
}
p = combine_buf;
} else {
cnt &= -sizeof(combine_buf); /* round down to multiple of 1024 */
}
if (cnt > remaining)
cnt = remaining;
if (!cnt)
break;
if (cnt > dev->max_transfer)
cnt = dev->max_transfer;
dbg_printf("%s:foffset=%x, cnt=%x, remaining=%x\n", __func__, foffset, cnt, remaining);
dbg_dump_long(p, cnt, ld->dladdr + transferSize, 0);
err = do_data_transfer(dev, p, cnt);
if (err < 0) {
printf("%s:foffset=%x, cnt=%x, remaining=%x, err=%d\n", __func__, foffset, cnt, remaining, err);
return err;
}
if (!err)
break;
transferSize += err;
foffset += err;
}
printf("\n<<<%i, %i bytes>>>\n", fsize, transferSize);
if (dev->mode == MODE_HID) {
unsigned int sec, status;
err = do_response(dev, 3, &sec, false);
if (err)
return err;
err = do_response(dev, 4, &status, false);
if (err)
return err;
if (status == 0x88888888UL)
printf("succeeded");
else
printf("failed");
printf(" (security 0x%08x, status 0x%08x)\n", sec, status);
} else if (dev->mode == MODE_BULK) {
do_status(dev);
}
return transferSize;
}
static int jump(struct sdp_dev *dev, unsigned int header_addr)
{
unsigned char buf[MAX_PROTOCOL_SIZE];
int cmd_size;
int err;
unsigned int sec, status;
if (!dev->ops->fill_jump)
return 0;
cmd_size = dev->ops->fill_jump(buf, header_addr);
if (cmd_size <= 0)
return cmd_size;
printf("jumping to 0x%08x\n", header_addr);
err = do_command(dev, buf, cmd_size, 5);
if (err)
return err;
err = do_response(dev, 3, &sec, false);
if (err)
return err;
err = do_response(dev, 4, &status, true);
/*
* Documentation says: "This report is sent by device only in case of
* an error jumping to the given address..."
* If Report 4 fails, this is a good sign
* If Report 4 responds, there has been something gone wrong...
*/
if (!err) {
printf("failed (security 0x%08x, status 0x%08x)\n", sec, status);
return err;
}
return 0;
}
static int load_file_from_desc(struct sdp_dev *dev, struct sdp_work *curr,
struct load_desc *ld)
{
int ret;
unsigned file_base;
unsigned char type;
unsigned skip = 0;
unsigned fsize;
unsigned transferSize=0;
unsigned cnt;
if (!ld->dladdr) {
printf("\nunknown load address\n");
return -3;
}
type = (curr->plug || curr->jump_mode) ? FT_APP : FT_LOAD_ONLY;
if (dev->mode == MODE_BULK && type == FT_APP) {
/*
* There is no jump command. boot ROM requires the download
* to start at header address
*/
ld->dladdr = ld->header_addr;
}
if (ld->verify) {
if ((type == FT_APP) && (dev->mode != MODE_HID)) {
type = FT_LOAD_ONLY;
ld->verify = 2;
}
}
file_base = ld->header_addr - ld->header_offset;
if (file_base > ld->dladdr) {
ld->max_length -= (file_base - ld->dladdr);
ld->dladdr = file_base;
}
dbg_printf("skip=%x cnt=%x dladdr=%x file_base=%x fsize=%x max_length=%x\n", skip, ld->buf_cnt, ld->dladdr, file_base, ld->fsize, ld->max_length);
skip = ld->dladdr - file_base;
fsize = ld->fsize;
if (skip > fsize) {
printf("skip(0x%08x) > fsize(0x%08x) file_base=0x%08x, header_offset=0x%x\n",
skip, fsize, file_base, ld->header_offset);
ret = -4;
goto cleanup;
}
fsize -= skip;
if (fsize > ld->max_length)
fsize = ld->max_length;
printf("\nloading binary file(%s) to %08x, skip=%x, fsize=%x type=%x\n", curr->filename, ld->dladdr, skip, fsize, type);
ret = load_file(dev, ld, skip, fsize, type);
if (ret < 0)
goto cleanup;
transferSize = ret;
if (ld->verify) {
ret = verify_memory(dev, ld, skip, fsize);
if (ret < 0)
goto cleanup;
if (ld->verify == 2) {
cnt = fsize;
if (cnt > 64)
cnt = 64;
/*
* This will set the right header address
* for bulk mode, which has no jump command
*/
ret = load_file(dev, ld, ld->header_offset, cnt,
FT_APP);
if (ret < 0)
goto cleanup;
}
}
ret = (fsize <= transferSize) ? 0 : -16;
cleanup:
return ret;
}
static int is_header(struct sdp_dev *dev, unsigned char *p)
{
switch (dev->header_type) {
case HDR_MX51:
{
struct flash_header_v1 *hdr = (struct flash_header_v1 *)p;
if (hdr->app_barker == 0xb1)
return 1;
break;
}
case HDR_MX53:
{
struct flash_header_v2 *hdr = (struct flash_header_v2 *)p;
struct ivt_header *ivt = &hdr->header;
if (ivt->tag == IVT_HEADER_TAG &&
(ivt->version == IVT_VERSION || ivt->version == IVT_VERSION_IMX8M))
return 1;
}
case HDR_UBOOT:
{
image_header_t *image = (image_header_t *)p;
if (BE32(image->ih_magic) == IH_MAGIC)
return 1;
}
}
return 0;
}
static void init_header(struct sdp_dev *dev, struct load_desc *ld)
{
struct sdp_work *curr = ld->curr;
memset(ld->writeable_header, 0, sizeof(ld->writeable_header));
switch (dev->header_type) {
case HDR_MX51:
{
struct flash_header_v1 *hdr = (struct flash_header_v1 *)ld->writeable_header;
unsigned char *p = (unsigned char *)(hdr + 1);
unsigned size;
unsigned extra_space = ((sizeof(struct flash_header_v1) + 4 - 1) | 0x3f) + 1;
ld->max_length += extra_space;
size = ld->max_length;
hdr->app_start_addr = curr->jump_addr;
hdr->app_barker = APP_BARKER;
hdr->dcd_ptr_ptr = ld->header_addr + offsetof(struct flash_header_v1, dcd_ptr);
hdr->app_dest_ptr = ld->dladdr;
*p++ = (unsigned char)size;
size >>= 8;
*p++ = (unsigned char)size;
size >>= 8;
*p++ = (unsigned char)size;
size >>= 8;
*p = (unsigned char)size;
break;
}
case HDR_MX53:
{
struct flash_header_v2 *hdr = (struct flash_header_v2 *)ld->writeable_header;
struct boot_data *bd = (struct boot_data *)(hdr+1);
unsigned extra_space = ((sizeof(struct flash_header_v2) + sizeof(struct boot_data) - 1) | 0x3f) + 1;
hdr->header.tag = IVT_HEADER_TAG;
hdr->header.length = BE16(sizeof(*hdr));
hdr->header.version = IVT_VERSION;
hdr->start_addr = curr->jump_addr;
hdr->boot_data_ptr = ld->header_addr + sizeof(*hdr);
hdr->self_ptr = ld->header_addr;
bd->dest = ld->dladdr;
ld->max_length += extra_space;
bd->image_len = ld->max_length;
break;
}
case HDR_UBOOT:
{
break;
}
}
}
/*
* Apply/load DCD table for v1 and v2 flash headers
*
* Returns 0 if successful or if there was no DCD table to download
* Returns -1 if the DCD table is invalid
*/
static int perform_dcd(struct sdp_dev *dev, unsigned char *p, unsigned char *file_start, unsigned cnt)
{
int ret = 0;
switch (dev->header_type) {
case HDR_MX51:
{
struct flash_header_v1 *hdr = (struct flash_header_v1 *)p;
ret = write_dcd_table_old(dev, hdr, file_start, cnt);
dbg_printf("dcd_ptr=0x%08x\n", hdr->dcd_ptr);
if (ret < 0)
return ret;
break;
}
case HDR_MX53:
{
#define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self_ptr)
struct flash_header_v2 *hdr = (struct flash_header_v2 *)p;
unsigned char* file_end = file_start + cnt;
unsigned char *dcd_end, *dcd_start;
struct dcd_v2 *dcd;
int length;
if (!hdr->dcd_ptr) {
printf("No DCD table\n");
return 0; //nothing to do
}
dcd_start = hdr->dcd_ptr + cvt_dest_to_src;
if ((dcd_start < file_start) || (dcd_start + 4) > file_end) {
printf("bad dcd_ptr %08x\n", hdr->dcd_ptr);
return -1;
}
dcd = (struct dcd_v2 *)dcd_start;
if (dcd->header.tag != DCD_HEADER_TAG ||
dcd->header.version != DCD_VERSION) {
printf("Unknown DCD header tag/version\n");
return -1;
}
length = BE16(dcd->header.length);
if (length == 0) {
printf("No DCD table, skip\n");
return 0;
}
/* Check whether DCD length is longer than file */
dcd_end = ((unsigned char *)dcd) + length;
if (dcd_end > file_end) {
printf("Bad dcd length 0x%08x\n", length);
return -1;
}
if (dev->mode == MODE_HID) {
ret = write_dcd(dev, dcd);
} else {
// For processors that don't support the WRITE_DCD command (i.MX5x)
ret = write_dcd_table_ivt(dev, dcd);
}
dbg_printf("dcd_ptr=0x%08x\n", hdr->dcd_ptr);
if (ret < 0)
return ret;
break;
}
}
return 0;
}
static int clear_dcd_ptr(struct sdp_dev *dev, unsigned char *p)
{
switch (dev->header_type) {
case HDR_MX51:
{
struct flash_header_v1 *hdr = (struct flash_header_v1 *)p;
if (hdr->dcd_ptr) {
printf("clear dcd_ptr=0x%08x\n", hdr->dcd_ptr);
hdr->dcd_ptr = 0;
}
break;
}
case HDR_MX53:
{
struct flash_header_v2 *hdr = (struct flash_header_v2 *)p;
if (hdr->dcd_ptr) {
printf("clear dcd_ptr=0x%08x\n", hdr->dcd_ptr);
hdr->dcd_ptr = 0;
}
break;
}
}
return 0;
}
static int get_dl_start(struct sdp_dev *dev, unsigned char *p,
struct load_desc *ld, unsigned int clear_boot_data)
{
unsigned char* file_end = ld->buf_start + ld->buf_cnt;
switch (dev->header_type) {
case HDR_MX51:
{
struct flash_header_v1 *hdr = (struct flash_header_v1 *)p;
unsigned char *dcd_end;
unsigned char* dcd;
int err = get_dcd_range_old(hdr, ld->buf_start, ld->buf_cnt, &dcd, &dcd_end);
ld->dladdr = hdr->app_dest_ptr;
ld->header_addr = hdr->dcd_ptr_ptr - offsetof(struct flash_header_v1, dcd_ptr);
ld->plugin = 0;
if (err >= 0) {
ld->max_length = dcd_end[0] | (dcd_end[1] << 8) | (dcd_end[2] << 16) | (dcd_end[3] << 24);
}
break;
}
case HDR_MX53:
{
struct boot_data *bd;
unsigned char* p1;
uint32_t *bd1;
unsigned offset;
struct flash_header_v2 *hdr = (struct flash_header_v2 *)p;
ld->dladdr = hdr->self_ptr;
ld->header_addr = hdr->self_ptr;
p1 = (hdr->boot_data_ptr + cvt_dest_to_src);
if ((p1 < ld->buf_start) || ((p1 + 4) > file_end)) {
printf("bad boot_data_ptr %08x\n", hdr->boot_data_ptr);
return -1;
}
bd = (struct boot_data *)p1;
ld->dladdr = bd->dest;
ld->max_length = bd->image_len;
ld->plugin = bd->plugin;
offset = ((unsigned char *)&bd->plugin) - p;
if (offset <= sizeof(ld->writeable_header) - 4) {
bd1 = (uint32_t *)(ld->writeable_header + offset);
*bd1 = 0;
} else {
printf("Can't clear plugin flag\n");
}
if (clear_boot_data) {
printf("Setting boot_data_ptr to 0\n");
hdr->boot_data_ptr = 0;
}
break;
}
case HDR_UBOOT:
{
image_header_t *hdr = (image_header_t *)p;
ld->dladdr = BE32(hdr->ih_load) - sizeof(image_header_t);
ld->header_addr = ld->dladdr;
}
}
return 0;
}
static unsigned offset_search_list[] = {0, 0x400, 0x8400};
static int process_header(struct sdp_dev *dev, struct sdp_work *curr,
struct load_desc *ld)
{
int ret;
unsigned header_max = 0x800 + curr->load_skip;
unsigned header_inc = 0;
unsigned search_index = 0;
int header_cnt = 0;
unsigned char *p;
int hdmi_ivt = 0;
int found = 0;
while (1) {
if (header_inc) {
ld->header_offset += header_inc;
if (ld->header_offset >= header_max)
break;
} else {
if (search_index >= ARRAY_SIZE(offset_search_list))
break;
ld->header_offset = curr->load_skip + offset_search_list[search_index++];
}
if ((ld->header_offset < ld->buf_offset) ||
(ld->header_offset - ld->buf_offset + 32 > ld->buf_cnt)) {
fseek(ld->xfile, ld->header_offset, SEEK_SET);
ld->buf_offset = ld->header_offset;
ld->buf_cnt = fread(ld->buf_start, 1, ld->buf_size, ld->xfile);
if (ld->buf_cnt < 32)
break;
}
p = ld->buf_start + ld->header_offset - ld->buf_offset;
if (!is_header(dev, p))
continue;
dbg_printf("%s: header_offset=%x, %02x%02x%02x%02x\n", __func__,
ld->header_offset, p[3], p[2], p[1], p[0]);
memcpy(ld->writeable_header, p,
sizeof(ld->writeable_header));
ret = get_dl_start(dev, p, ld, curr->clear_boot_data);
if (ret < 0) {
printf("!!get_dl_start returned %i\n", ret);
return ret;
}
if (curr->dcd) {
ret = perform_dcd(dev, p, ld->buf_start, ld->buf_cnt);
#if 1
clear_dcd_ptr(dev, ld->writeable_header);
#endif
if (ret < 0) {
printf("!!perform_dcd returned %i\n", ret);
return ret;
}
curr->dcd = 0;
if ((!curr->jump_mode) && (!curr->plug)) {
printf("!!dcd done, nothing else requested\n");
return 0;
}
}
if (curr->clear_dcd) {
ret = clear_dcd_ptr(dev, ld->writeable_header);
if (ret < 0) {
printf("!!clear_dcd returned %i\n", ret);
return ret;
}
}
if (ld->plugin & HDMI_IMAGE_FLAG_MASK) {
if (!hdmi_ivt) {
hdmi_ivt++;
header_inc = 0x1c00 - 0x1000 + ld->max_length;
header_max = ld->header_offset + header_inc + 0x400;
continue;
}
header_inc = ld->dladdr - ld->header_addr + ld->max_length + 0x400;
header_max = ld->header_offset + header_inc + 0x400;
continue;
}
if ((ld->plugin & PLUGIN_IMAGE_FLAG_MASK) && (!curr->plug) && (!header_cnt)) {
header_cnt++;
header_max = ld->header_offset + ld->max_length + 0x400;
printf("header_max=%x\n", header_max);
header_inc = 4;
} else {
if (!ld->plugin)
curr->plug = 0;
if (curr->jump_mode == J_HEADER2) {
if (!found) {
found++;
ld->header_offset += ld->dladdr - ld->header_addr + ld->max_length;
header_inc = 0x400;
header_max = ld->header_offset + 0x400 * 128;
continue;
}
}
return 0;
}
}
printf("header not found %x:%x, %x\n", ld->header_offset, *(unsigned int *)p, ld->buf_cnt);
return -EINVAL;
}
static int do_download(struct sdp_dev *dev, struct sdp_work *curr, int verify)
{
int ret;
struct load_desc ld = {0};
print_sdp_work(curr);
ld.curr = curr;
ld.verify = verify;
ld.xfile = fopen(curr->filename, "rb" );
if (!ld.xfile) {
printf("\nerror, can not open input file: %s\n", curr->filename);
return -5;
}
ld.buf_size = (1024*16);
ld.buf_start = malloc(ld.buf_size);
if (!ld.buf_start) {
printf("\nerror, out of memory\n");
ret = -2;
goto cleanup;
}
ld.fsize = get_file_size(ld.xfile);
ld.max_length = ld.fsize;
if (ld.max_length > curr->load_skip) {
ld.max_length -= curr->load_skip;
} else {
printf("error, skipping past end of file\n");
ret = -1;
goto cleanup;
}
if (curr->load_size && (ld.max_length > curr->load_size))
ld.max_length = curr->load_size;
if (curr->dcd || curr->clear_dcd || curr->plug || (curr->jump_mode >= J_HEADER)) {
ret = process_header(dev, curr, &ld);
if (ret < 0)
goto cleanup;
if ((!curr->jump_mode) && (!curr->plug)) {
/* nothing else requested */
ret = 0;
goto cleanup;
}
} else {
ld.dladdr = curr->load_addr;
ld.header_addr = ld.dladdr + ld.max_length;
ld.header_offset = curr->load_skip + ld.max_length;
if (curr->jump_mode == J_ADDR_HEADER) {
unsigned cnt = ld.max_length;
init_header(dev, &ld);
/* If the header is at EOF, fsize needs increased */
ld.fsize += ld.max_length - cnt;
dbg_dump_long((unsigned char *)ld.writeable_header, ld.max_length - cnt, ld.header_addr, 0);
} else if (curr->jump_mode == J_ADDR_DIRECT) {
ld.header_addr = curr->jump_addr;
ld.header_offset = 0;
}
}
if (ld.plugin && (!curr->plug)) {
printf("Only plugin header found\n");
ret = -1;
goto cleanup;
}
ret = load_file_from_desc(dev, curr, &ld);
/*
* Any command will initiate jump for bulk devices, no need to
* explicitly send a jump command
*/
if (dev->mode == MODE_HID && (curr->plug || curr->jump_mode)) {
ret = jump(dev, ld.header_addr);
if (ret < 0)
goto cleanup;
}
cleanup:
fclose(ld.xfile);
free(ld.buf_start);
return ret;
}
int do_work(struct sdp_dev *p_id, struct sdp_work **work, int verify)
{
struct sdp_work *curr = *work;
int err = 0;
err = do_status(p_id);
if (err) {
fprintf(stderr, "status failed\n");
return err;
}
while (curr) {
/* Do current job */
if (curr->mem)
perform_mem_work(p_id, curr->mem);
if (curr->filename[0])
err = do_download(p_id, curr, verify);
if (err) {
fprintf(stderr, "do_download failed, err=%d\n", err);
do_status(p_id);
break;
}
/* Check if more work is to do... */
if (!curr->next) {
/*
* If only one job, but with a plug-in is specified
* reexecute the same job, but this time download the
* image. This allows to specify a single file with
* plugin and image, and imx_usb will download & run
* the plugin first and then the image.
* NOTE: If the file does not contain a plugin,
* DoIRomDownload->process_header will set curr->plug
* to 0, so we won't download the same image twice...
*/
if (curr->plug) {
curr->plug = 0;
} else {
curr = NULL;
break;
}
} else {
curr = curr->next;
}
/*
* Check if device is still here, otherwise return
* with work (retry)
*/
err = do_status(p_id);
if (err < 0) {
err = 0;
break;
}
}
*work = curr;
return err;
}
================================================
FILE: imx_sdp.h
================================================
/*
* imx_sdp:
* Interface of the Serial Download Protocol (SDP) for i.MX/Vybrid
* series processors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __IMX_SDP_H__
#define __IMX_SDP_H__
#include <stdint.h>
struct ram_area {
unsigned start;
unsigned size;
};
struct mem_work {
struct mem_work *next;
unsigned type;
#define MEM_TYPE_READ 0
#define MEM_TYPE_WRITE 1
#define MEM_TYPE_MODIFY 2
unsigned vals[3];
};
struct sdp_work;
struct sdp_work {
struct sdp_work *next;
struct mem_work *mem;
char filename[256];
unsigned char dcd;
unsigned char clear_dcd; //means clear dcd_ptr
unsigned char clear_boot_data; //means clear boot data ptr
unsigned char plug;
#define J_ADDR_DIRECT 1
#define J_ADDR_HEADER 2
#define J_HEADER 3
#define J_HEADER2 4
unsigned char jump_mode;
unsigned load_addr;
unsigned jump_addr;
unsigned load_size;
unsigned load_skip;
};
struct sdp_dev;
struct protocol_ops {
int (*fill_read_reg)(unsigned char *buf, unsigned addr, unsigned cnt);
int (*fill_write_reg)(unsigned char *buf, unsigned addr, unsigned cnt);
int (*fill_status)(unsigned char *buf);
int (*fill_dl_dcd)(unsigned char *buf, unsigned dcd_addr, int length);
int (*fill_write_file)(unsigned char *buf, unsigned dladdr, unsigned fsize, unsigned char type);
int (*fill_jump)(unsigned char *buf, unsigned header_addr);
int (*get_cmd_addr_cnt)(unsigned char *buf, uint16_t *cmd, uint32_t *addr, uint32_t *cnt);
/*
* dev - SDP devce (this structure)
* report - HID Report
* p - pointer to buffer
* size - size of buffer (used for send and USB receive length)
* expected - the expected amount of data (used for UART receive)
* last_trans - the actually transfered bytes
*/
int (*transfer)(struct sdp_dev *dev, int report, unsigned char *p, unsigned int size,
unsigned int expected, int* last_trans);
};
struct sdp_dev {
char name[64];
unsigned short max_transfer;
#define MODE_HID 0
#define MODE_BULK 1
#define MODE_SDPS 2
unsigned char mode;
#define HDR_NONE 0
#define HDR_MX51 1
#define HDR_MX53 2
#define HDR_UBOOT 3
unsigned char header_type;
unsigned dcd_addr;
struct ram_area ram[8];
struct sdp_work *work;
struct protocol_ops *ops;
void *priv;
unsigned char use_ep1;
unsigned char no_hid_cmd;
};
#define HAB_SECMODE_PROD 0x12343412
#define HAB_SECMODE_DEV 0x56787856
/*
* Section 8.7.2 of the i.MX6DQ/UL/SoloX RM:
* The maximum size of the DCD limited to 1768 bytes.
*/
#define HAB_MAX_DCD_SIZE 1768
#define MAX_PROTOCOL_SIZE 32
#define CMD_INVAL 0x00
#define CMD_READ_REG 0x0101
#define CMD_WRITE_REG 0x0202
#define CMD_WRITE_FILE 0x0404
#define CMD_ERROR_STATUS 0x0505
#define CMD_WRITE_DCD 0x0a0a
#define CMD_JUMP_ADDRESS 0x0b0b
void dump_long(unsigned char *src, unsigned cnt, unsigned addr, unsigned skip);
void dump_bytes(unsigned char *src, unsigned cnt, unsigned addr);
int do_work(struct sdp_dev *p_id, struct sdp_work **work, int verify);
#endif /* __IMX_SDP_H__ */
================================================
FILE: imx_sdp_simulation.c
================================================
/*
* imx_sdp_simulation:
* A simple client side implementation of the Serial Download Protocol (SDP)
* for testing.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portable.h"
#include "imx_sdp.h"
#include "image.h"
struct sim_memory *head;
struct sim_memory {
struct sim_memory *next;
unsigned int addr;
unsigned int len;
unsigned char *buf;
int offset;
};
int do_simulation(struct sdp_dev *dev, int report, unsigned char *p, unsigned int count,
unsigned int expected, int* last_trans)
{
static unsigned char cur_cmd[MAX_PROTOCOL_SIZE];
static struct sim_memory *cur_mem;
unsigned int offset;
unsigned mem_addr;
int cmd_size;
uint16_t cmd;
uint32_t addr;
uint32_t cnt;
if (!dev->ops->get_cmd_addr_cnt)
return -EINVAL;
switch (report) {
case 1:
cmd_size = dev->ops->get_cmd_addr_cnt(p, &cmd, &addr, &cnt);
/* Copy command */
memcpy(cur_cmd, p, cmd_size);
printf("cmd: %04x\n", cmd);
switch (cmd) {
case CMD_WRITE_FILE:
case CMD_WRITE_DCD:
if (!head) {
cur_mem = head = malloc(sizeof(*cur_mem));
} else {
cur_mem = head;
while (cur_mem->next)
cur_mem = cur_mem->next;
cur_mem->next = malloc(sizeof(*cur_mem));
cur_mem = cur_mem->next;
}
cur_mem->next = NULL;
cur_mem->addr = addr;
cur_mem->len = cnt;
cur_mem->buf = malloc(cur_mem->len);
cur_mem->offset = 0;
break;
case CMD_READ_REG:
cur_mem = head;
while (cur_mem) {
if (cur_mem->addr <= addr &&
cur_mem->addr + cur_mem->len > addr) {
break;
}
cur_mem = cur_mem->next;
}
break;
}
break;
case 2:
/* Data phase, ignore */
memcpy(cur_mem->buf + cur_mem->offset, p, count);
cur_mem->offset += count;
break;
case 3:
/* Simulate security configuration open */
*((unsigned int *)p) = BE32(0x56787856);
break;
case 4:
dev->ops->get_cmd_addr_cnt(cur_cmd, &cmd, &addr, &cnt);
/* Return sensible status */
switch (cmd) {
case CMD_WRITE_FILE:
*((unsigned int *)p) = BE32(0x88888888UL);
break;
case CMD_WRITE_DCD:
*((unsigned int *)p) = BE32(0x128a8a12UL);
break;
case CMD_READ_REG:
cur_mem = head;
mem_addr = addr;
while (cur_mem) {
if (cur_mem->addr <= mem_addr &&
cur_mem->addr + cur_mem->len > mem_addr) {
if ((mem_addr + count) > (cur_mem->addr + cur_mem->len))
return -EIO;
break;
}
cur_mem = cur_mem->next;
}
if (!cur_mem)
return -EIO;
offset = mem_addr - cur_mem->addr;
memcpy(p, cur_mem->buf + offset, cnt);
break;
case CMD_JUMP_ADDRESS:
/* A successful jump returns nothing on Report 4 */
return -7;
}
break;
default:
break;
}
return 0;
}
void do_simulation_cleanup(void)
{
struct sim_memory *cur_mem = head;
while (cur_mem) {
struct sim_memory *free_mem = cur_mem;
cur_mem = cur_mem->next;
free(free_mem);
}
}
================================================
FILE: imx_sdp_simulation.h
================================================
/*
* imx_sdp_simulation:
* A simple client side implementation of the Serial Download Protocol (SDP)
* for testing.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __IMX_SDP_SIMULATION_H__
#define __IMX_SDP_SIMULATION_H__
int do_simulation(struct sdp_dev *dev, int report, unsigned char *p, unsigned int cnt,
unsigned int expected, int* last_trans);
void do_simulation_cleanup(void);
#endif /* __IMX_SDP_SIMULATION_H__ */
================================================
FILE: imx_uart.c
================================================
/*
* imx_uart:
*
* Program to download and execute an image over the serial boot protocol
* on i.MX series processors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <fcntl.h>
#ifndef WIN32
#include <termios.h>
#include <sys/ioctl.h>
#endif
#include "portable.h"
#include "imx_sdp.h"
#include "imx_loader.h"
#include "imx_loader_config.h"
extern int debugmode;
#define get_min(a, b) (((a) < (b)) ? (a) : (b))
int transfer_uart(struct sdp_dev *dev, int report, unsigned char *p, unsigned size,
unsigned int expected, int* last_trans)
{
int fd = *(int *)dev->priv;
if (report < 3) {
*last_trans = write(fd, p, size);
} else {
// Read...
int ret;
*last_trans = 0;
while (*last_trans < (int)expected)
{
ret = read(fd, p, expected - *last_trans);
if (ret < 0)
return ret;
// err is transfered bytes...
*last_trans += ret;
p += ret;
}
}
return 0;
}
#ifndef WIN32
int uart_connect(int *uart_fd, char const *tty, int usertscts, int associate, struct termios *orig)
#else
int uart_connect(int *uart_fd, char const *tty, int usertscts, int associate, DCB* orig)
#endif
{
int err = 0, count = 0;
int retry = 10;
#ifndef WIN32
int flags = O_RDWR | O_NOCTTY | O_SYNC;
struct termios key;
#else
int flags = O_RDWR | _O_BINARY;
DCB dcb;
COMMTIMEOUTS timeouts;
HANDLE handle;
#endif
char magic[] = { 0x23, 0x45, 0x45, 0x23 };
char magic_response[4];
char *buf;
#ifndef WIN32
memset(&key,0,sizeof(key));
#endif
memset(&magic_response,0,sizeof(magic_response));
*uart_fd = open(tty, flags);
if (*uart_fd < 0) {
printf("tty %s\n", tty);
fprintf(stdout, "open() failed: %s\n", strerror(errno));
return *uart_fd;
}
#ifndef WIN32
// Get original terminal settings
err = tcgetattr(*uart_fd, orig);
// 8 data bits
key.c_cflag |= CS8;
key.c_cflag |= CLOCAL | CREAD;
if (usertscts)
key.c_cflag |= CRTSCTS;
key.c_cflag |= B115200;
// Enable blocking read, 0.5s timeout...
key.c_lflag &= ~ICANON; // Set non-canonical mode
key.c_cc[VTIME] = 5;
err = tcsetattr(*uart_fd, TCSANOW, &key);
if (err < 0) {
fprintf(stdout, "tcsetattr() failed: %s\n", strerror(errno));
close(*uart_fd);
return err;
}
err = tcflush(*uart_fd, TCIOFLUSH);
#else
handle=(HANDLE)_get_osfhandle(*uart_fd);
orig->DCBlength=sizeof(DCB);
GetCommState(handle,orig);
memset(&dcb,0,sizeof(DCB));
dcb.DCBlength=sizeof(DCB);
dcb.fBinary=TRUE;
dcb.fParity=FALSE;
dcb.BaudRate=CBR_115200;
dcb.ByteSize=8;
if (usertscts)
{
dcb.fRtsControl=RTS_CONTROL_ENABLE;
dcb.fOutxCtsFlow=TRUE;
}
if (!SetCommState(handle,&dcb))
{
fprintf(stdout, "SetCommState() failed: %d\n", GetLastError());
close(*uart_fd);
return err;
}
memset(&timeouts,0,sizeof(COMMTIMEOUTS));
timeouts.ReadIntervalTimeout=MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier=MAXDWORD;
timeouts.ReadTotalTimeoutConstant=500;
if (!SetCommTimeouts(handle,&timeouts))
{
fprintf(stdout, "SetCommTimeouts() failed: %d\n", GetLastError());
close(*uart_fd);
return err;
}
if (!PurgeComm(handle,PURGE_TXABORT|PURGE_RXABORT))
{
fprintf(stdout, "PurgeComm() failed: %d\n", GetLastError());
close(*uart_fd);
return err;
}
#endif
if (!associate)
return err;
// Association phase, send and receive 0x23454523
printf("starting associating phase");
while(retry--) {
#ifndef WIN32
// Flush again before retrying
err = tcflush(*uart_fd, TCIOFLUSH);
#endif
write(*uart_fd, magic, sizeof(magic));
buf = magic_response;
count = 0;
while (count < 4) {
err = read(*uart_fd, buf, 4 - count);
/* read timeout.. */
if (err <= 0)
break;
count += err;
buf += err;
}
if (!memcmp(magic, magic_response, sizeof(magic_response)))
break;
printf(".");
fflush(stdout);
#ifndef WIN32
err = tcflush(*uart_fd, TCIOFLUSH);
#endif
msleep(1000);
}
printf("\n");
fflush(stdout);
if (!retry) {
fprintf(stderr, "associating phase failed, make sure the device"
" is in recovery mode\n");
close(*uart_fd);
return -2;
}
if (memcmp(magic, magic_response, sizeof(magic_response))) {
fprintf(stderr, "magic missmatch, response was 0x%08x\n",
*(uint32_t *)magic_response);
close(*uart_fd);
return -3;
}
fprintf(stderr, "association phase succeeded, response was 0x%08x\n",
*(uint32_t *)magic_response);
return 0;
}
#ifndef WIN32
void uart_close(int *uart_fd, struct termios *orig)
#else
void uart_close(int *uart_fd, DCB* orig)
#endif
{
#ifndef WIN32
int err;
// Restore original terminal settings
err = tcsetattr(*uart_fd, TCSAFLUSH, orig);
if (err < 0)
fprintf(stdout, "tcsetattr() failed: %s\n", strerror(errno));
#else
HANDLE handle;
handle=(HANDLE)_get_osfhandle(*uart_fd);
SetCommState(handle,orig);
#endif
close(*uart_fd);
}
void print_usage(void)
{
printf("Usage: imx_uart [OPTIONS...] UART CONFIG [JOBS...]\n"
#ifndef WIN32
" e.g. imx_uart -n /dev/ttyUSB0 vybrid_usb_work.conf u-boot.imx\n"
#else
" e.g. imx_uart -n COM1: vybrid_uart_work.conf eboot.img\n"
#endif
"Load data on target connected to UART using serial download protocol as\n"
"configured in CONFIG file.\n"
"\n"
"Where OPTIONS are\n"
" -h --help Show this help\n"
" -v --verify Verify downloaded data\n"
" -n --no-rtscts Do not use RTS/CTS flow control\n"
" Default is to use RTS/CTS, Vybrid requires them\n"
" -N --no-association Do not do serial Association Phase\n"
" -d --debugmode Enable debug logs\n"
"\n"
"And where [JOBS...] are\n"
" FILE [-lLOADADDR] [-sSIZE] ...\n"
"Multiple jobs can be configured. The first job is treated special, load\n"
"address, jump address, and length are read from the IVT header. If no job\n"
"is specified, the jobs defined in the target specific configuration file\n"
"is being used.\n");
}
int parse_opts(int argc, char * const *argv, char const **ttyfile,
char const **conffile, int *verify, int *usertscts,
int *associate, struct sdp_work **cmd_head)
{
char c;
*conffile = NULL;
*ttyfile = NULL;
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"verify", no_argument, 0, 'v' },
{"version", no_argument, 0, 'V' },
{"debugmode", no_argument, 0, 'd' },
{"no-rtscts", no_argument, 0, 'n' },
{"no-association", no_argument, 0, 'N' },
{0, 0, 0, 0 },
};
while ((c = getopt_long(argc, argv, "+hdvVnN", long_options, NULL)) != -1) {
switch (c)
{
case 'h':
case '?':
print_usage();
return 1;
case 'd':
debugmode = 1; /* global extern */
break;
case 'n':
*usertscts = 0;
break;
case 'N':
*associate = 0;
break;
case 'v':
*verify = 1;
break;
case 'V':
printf("imx_usb " IMX_LOADER_VERSION "\n");
return 1;
}
}
// Options parsed, get mandatory arguments...
if (optind >= argc) {
fprintf(stderr, "non optional argument UART is missing\n");
return -1;
}
*ttyfile = argv[optind];
optind++;
if (optind >= argc) {
fprintf(stderr, "non optional argument CONFIG is missing\n");
return -1;
}
*conffile = argv[optind];
optind++;
if (optind < argc) {
// Parse optional job arguments...
*cmd_head = parse_cmd_args(argc - optind, &argv[optind]);
}
return 0;
}
void sdps_init_ops(struct sdp_dev *dev)
{
printf("sdps not supported\n");
exit(1);
}
#define ARRAY_SIZE(w) sizeof(w)/sizeof(w[0])
int main(int argc, char * const argv[])
{
struct sdp_dev *p_id;
int err = 0;
int verify = 0;
int usertscts = 1;
int associate = 1;
int uart_fd;
struct sdp_work *curr;
char const *conf;
char const *ttyfile;
char const *conffilepath;
char const *conffile;
char const *basepath;
#ifndef WIN32
struct termios orig;
#else
DCB orig;
#endif
curr=NULL;
err = parse_opts(argc, argv, &ttyfile, &conffilepath, &verify,
&usertscts, &associate, &curr);
if (err < 0)
return EXIT_FAILURE;
else if (err > 0)
return EXIT_SUCCESS;
// Get machine specific configuration file..
if ((conffile = strrchr(conffilepath, PATH_SEPARATOR)) == NULL) {
// Only a file was given as configuration
basepath = get_base_path(argv[0]);
conffile = conffilepath;
} else {
// A whole path is given as configuration
basepath = get_base_path(conffilepath);
conffile++; // Filename starts after slash
}
conf = conf_file_name(conffile, basepath, get_global_conf_path());
if (conf == NULL)
return -1;
p_id = parse_conf(conf);
if (!p_id)
return -1;
// Open UART and start associating phase...
err = uart_connect(&uart_fd, ttyfile, usertscts, associate, &orig);
if (err < 0)
return EXIT_FAILURE;
p_id->ops->transfer = &transfer_uart;
// UART private pointer is TTY file descriptor...
p_id->priv = &uart_fd;
// By default, use work from config file...
if (curr == NULL)
curr = p_id->work;
err = do_work(p_id, &curr, verify);
dbg_printf("do_work finished with err=%d, curr=%p\n", err, curr);
uart_close(&uart_fd, &orig);
return err;
}
================================================
FILE: imx_usb.c
================================================
/*
* imx_usb:
*
* Program to download and execute an image over the USB boot protocol
* on i.MX series processors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#ifdef __FreeBSD__
#include <libusb.h>
#else
#include <libusb-1.0/libusb.h>
#endif
#include "portable.h"
#include "imx_sdp.h"
#include "imx_sdp_simulation.h"
#include "imx_loader.h"
#include "imx_loader_config.h"
struct mach_id;
struct mach_id {
struct mach_id *next;
struct mach_id *nextbatch;
unsigned short vid;
unsigned short pid;
char file_name[256];
};
static void print_devs(libusb_device **devs)
{
int j, k, l;
int i = 0;
for (;;) {
struct libusb_device_descriptor desc;
struct libusb_config_descriptor *config;
libusb_device *dev = devs[i++];
if (!dev)
break;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor");
return;
}
libusb_get_config_descriptor(dev, 0, &config);
printf("%04x:%04x (bus %d, device %d) bNumInterfaces:%i\n",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev),
config->bNumInterfaces);
for (j = 0; j < config->bNumInterfaces; j++) {
const struct libusb_interface *inter = &config->interface[j];
printf(" alternates:%i\n", inter->num_altsetting);
for (k = 0; k < inter->num_altsetting; k++) {
const struct libusb_interface_descriptor *interdesc = &inter->altsetting[k];
printf(" Interface Number: %i, Number of endpoints: %i\n",
interdesc->bInterfaceNumber, interdesc->bNumEndpoints);
for (l = 0; l < interdesc->bNumEndpoints; l++) {
const struct libusb_endpoint_descriptor *epdesc = &interdesc->endpoint[l];
printf(" Descriptor Type: %x, EP Address: %i, wMaxPacketSize: %i\n",
epdesc->bDescriptorType, epdesc->bEndpointAddress, epdesc->wMaxPacketSize);
}
}
}
libusb_free_config_descriptor(config);
}
}
static struct mach_id *parse_imx_mach(const char **pp)
{
unsigned short vid;
unsigned short pid;
struct mach_id *curr = NULL;
const char *p = *pp;
while (*p==' ') p++;
if (p[0] == '#')
return NULL;
vid = get_val(&p, 16);
if (p[0] != ':') {
printf("Syntax error(missing ':'): %s [%s]\n", p, *pp);
return NULL;
}
p++;
pid = get_val(&p, 16);
if (p[0] != ',') {
printf("Syntax error(missing ','): %s [%s]\n", p, *pp);
return NULL;
}
p++;
while (*p==' ') p++;
if (!(vid && pid)) {
printf("vid/pid cannot be 0: %s [%s]\n", p, *pp);
return NULL;
}
curr = (struct mach_id *)malloc(sizeof(struct mach_id));
curr->next = NULL;
curr->nextbatch = NULL;
curr->vid = vid;
curr->pid = pid;
p = move_string(curr->file_name, p, sizeof(curr->file_name) - 1);
*pp = p;
return curr;
}
/*
* Parse USB specific machine configuration
*/
static struct mach_id *parse_imx_conf(char const *filename)
{
char line[512];
struct mach_id *head = NULL;
struct mach_id *tail = NULL;
struct mach_id *curr = NULL;
const char *p;
FILE* xfile = fopen(filename, "rb" );
if (!xfile) {
printf("Could not open file: %s\n", filename);
return NULL;
}
while (fgets(line, sizeof(line), xfile) != NULL) {
p = line;
curr = parse_imx_mach(&p);
if (!curr)
continue;
if (!head)
head = curr;
if (tail)
tail->next = curr;
tail = curr;
printf("vid=0x%04x pid=0x%04x file_name=%s\n", curr->vid, curr->pid, curr->file_name);
while (p[0] == ',') {
p++;
// Second machine in batch...
curr->nextbatch = parse_imx_mach(&p);
curr = curr->nextbatch;
printf("-> vid=0x%04x pid=0x%04x file_name=%s\n", curr->vid, curr->pid, curr->file_name);
}
}
fclose(xfile);
return head;
}
static struct mach_id * imx_device(unsigned short vid, unsigned short pid, struct mach_id *p)
{
// printf("%s: vid=%x pid=%x\n", __func__, vid, pid);
while (p) {
if ((p->vid == vid) && (p->pid == pid))
return p;
p = p->next;
}
return NULL;
}
static libusb_device *find_imx_dev(libusb_device **devs, struct mach_id **pp_id, struct mach_id *list, int bus, int address)
{
int i = 0;
struct mach_id *p;
for (;;) {
struct libusb_device_descriptor desc;
libusb_device *dev = devs[i++];
if (!dev)
break;
if ((bus >= 0 && libusb_get_bus_number(dev) != bus) ||
(address >= 0 && libusb_get_device_address(dev) != address))
continue;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor");
return NULL;
}
p = imx_device(desc.idVendor, desc.idProduct, list);
if (p) {
*pp_id = p;
return dev;
}
}
fprintf(stderr, "no matching USB device found\n");
*pp_id = NULL;
return NULL;
}
// HID Class-Specific Requests values. See section 7.2 of the HID specifications
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
#define HID_REPORT_TYPE_INPUT 0x01
#define HID_REPORT_TYPE_OUTPUT 0x02
#define HID_REPORT_TYPE_FEATURE 0x03
#define CTRL_IN LIBUSB_ENDPOINT_IN |LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
#define CTRL_OUT LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
#define EP_IN 0x80
/*
* For HID class drivers, 4 reports are used to implement
* Serial Download protocol(SDP)
* Report 1 (control out endpoint) 16 byte SDP comand
* (total of 17 bytes with 1st byte report id of 0x01
* Report 2 (control out endpoint) data associated with report 1 commands
* (max size of 1025 with 1st byte of 0x02)
* Report 3 (interrupt in endpoint) HAB security state
* (max size of 5 bytes with 1st byte of 0x03)
* (0x12343412 production)
* (0x56787856 engineering)
* Report 4 (interrupt in endpoint) date associated with report 1 commands
* (max size of 65 bytes with 1st byte of 0x04)
*
*/
static int transfer_hid(struct sdp_dev *dev, int report, unsigned char *p, unsigned int cnt,
unsigned int expected, int* last_trans)
{
unsigned char tmp[1028];
int err;
struct libusb_device_handle *h = (struct libusb_device_handle *)dev->priv;
if (cnt > dev->max_transfer)
cnt = dev->max_transfer;
dbg_printf("report=%i, cnt=%x\n", report, cnt);
#ifdef DEBUG
if (report < 3)
dump_bytes(p, cnt, 0);
#endif
tmp[0] = (unsigned char)report;
if (report < 3) {
memcpy(&tmp[1], p, cnt);
if (report == 2)
cnt = dev->max_transfer;
if (!dev->use_ep1) {
err = libusb_control_transfer(h,
CTRL_OUT,
HID_SET_REPORT,
(HID_REPORT_TYPE_OUTPUT << 8) | report,
0,
tmp, cnt + 1, 1000);
*last_trans = (err > 0) ? err - 1 : 0;
} else {
*last_trans = 0;
err = libusb_interrupt_transfer(h, 1,
tmp, cnt + 1, last_trans, 1000);
if (err < 0) {
printf("%s: read error(%i)(%s), cnt=%i, last_trans=%i, %02x %02x %02x %02x\n",
__func__, err, libusb_strerror(err),
cnt, *last_trans, p[0], p[1], p[2], p[3]);
}
if (*last_trans)
*last_trans -= 1;
dbg_printf("%s: last_trans=%d\n", __func__, *last_trans);
}
if (err > 0)
err = 0;
} else {
*last_trans = 0;
memset(&tmp[1], 0, cnt);
err = libusb_interrupt_transfer(h, 1 + EP_IN, tmp, cnt + 1, last_trans, 1000);
dbg_printf("libusb_interrupt_transfer, err=%d, trans=%d\n", err,
*last_trans);
if (err >= 0) {
if (tmp[0] == (unsigned char)report) {
if (*last_trans > 1) {
*last_trans -= 1;
memcpy(p, &tmp[1], *last_trans);
}
} else {
printf("Unexpected report %i err=%i, cnt=%i, last_trans=%i, %02x %02x %02x %02x\n",
tmp[0], err, cnt, *last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
err = 0;
}
}
}
#ifdef DEBUG
if (report >= 3)
dump_bytes(p, cnt, 0);
#endif
return err;
}
/*
* For Bulk class drivers, the device is configured as
* EP0IN, EP0OUT control transfer
* EP1OUT - bulk out
* (max packet size of 512 bytes)
* EP2IN - bulk in
* (max packet size of 512 bytes)
*/
static int transfer_bulk(struct sdp_dev *dev, int report, unsigned char *p, unsigned int cnt,
unsigned int expected, int* last_trans)
{
int err;
struct libusb_device_handle *h = (struct libusb_device_handle *)dev->priv;
if (cnt > dev->max_transfer)
cnt = dev->max_transfer;
#ifdef DEBUG
printf("report=%i\n", report);
if (report < 3)
dump_bytes(p, cnt, 0);
#endif
*last_trans = 0;
err = libusb_bulk_transfer(h, (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
#ifdef DEBUG
if (report >= 3)
dump_bytes(p, cnt, 0);
#endif
return err;
}
int transfer_simulation(struct sdp_dev *dev, int report, unsigned char *p, unsigned int cnt,
unsigned int expected, int* last_trans)
{
int err = 0;
if (cnt > dev->max_transfer)
cnt = dev->max_transfer;
printf("report=%i, cnt=%d\n", report, cnt);
switch (report) {
case 1:
case 2:
dump_bytes(p, cnt, 0);
break;
case 3:
case 4:
memset(p, 0, cnt);
break;
}
err = do_simulation(dev, report, p, cnt, expected, last_trans);
/* On error, do not transmit anything */
if (err)
*last_trans = 0;
else
*last_trans = cnt;
return err;
}
#define ARRAY_SIZE(w) sizeof(w)/sizeof(w[0])
void print_usage(void)
{
printf("Usage: imx_usb [OPTIONS...] [JOBS...]\n"
" e.g. imx_usb -v u-boot.imx\n"
"Load data on target connected to USB using serial download protocol. The target\n"
"type is detected using USB ID, an appropriate configuration file.\n"
"\n"
"Where OPTIONS are\n"
" -h --help Show this help\n"
" -v --verify Verify downloaded data\n"
" -d --debugmode Enable debug logs\n"
" -c --configdir=DIR Reading configuration directory from non standard\n"
" directory.\n"
" -b --bus=NUM Filter bus number.\n"
" -D --device=NUM Filter device address.\n"
" -S --sim=VID:PID Simulate a device of VID:PID\n"
"\n"
"And where [JOBS...] are\n"
" FILE [-lLOADADDR] [-sSIZE] ...\n"
"Multiple jobs can be configured. The first job is treated special, load\n"
"address, jump address, and length are read from the IVT header. If no job\n"
"is specified, the jobs defined in the target specific configuration file\n"
"is being used.\n");
}
int do_simulation_dev(char const *base_path, char const *conf_path,
struct mach_id *list, int verify, struct sdp_work *cmd_head,
char const *vidpid)
{
int err;
struct mach_id *mach;
struct sdp_dev *p_id;
struct sdp_work *curr = NULL;
char const *conf;
unsigned short vid, pid;
sscanf(vidpid, "%hx:%hx", &vid, &pid);
printf("Simulating with vid=0x%04hx pid=0x%04hx\n", vid, pid);
mach = imx_device(vid, pid, list);
if (!mach) {
fprintf(stderr, "Could not find device vid=0x%04x pid=0x%04x\n",
vid, pid);
return -1;
}
// Get machine specific configuration file..
conf = conf_file_name(mach->file_name, base_path, conf_path);
if (conf == NULL)
return -1;
p_id = parse_conf(conf);
if (!p_id)
return -1;
p_id->ops->transfer = &transfer_simulation;
curr = p_id->work;
// Prefer work from command line, disable batch mode...
if (cmd_head) {
curr = cmd_head;
mach->nextbatch = NULL;
}
err = do_work(p_id, &curr, verify);
dbg_printf("do_work finished with err=%d, curr=%p\n", err, curr);
do_simulation_cleanup();
return err;
}
int do_autodetect_dev(char const *base_path, char const *conf_path,
struct mach_id *list, int verify, struct sdp_work *cmd_head,
int bus, int address)
{
struct sdp_dev *p_id;
struct mach_id *mach;
libusb_device **devs;
libusb_device *dev;
int err = 0;
ssize_t cnt;
struct sdp_work *curr = NULL;
libusb_device_handle *h = NULL;
char const *conf;
int retry;
int config = 0;
err = libusb_init(NULL);
if (err < 0)
return err;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0) {
err = LIBUSB_ERROR_NO_DEVICE;
goto out_deinit_usb;
}
if (debugmode)
print_devs(devs);
dev = find_imx_dev(devs, &mach, list, bus, address);
if (!dev) {
err = LIBUSB_ERROR_NO_DEVICE;
goto out_deinit_usb;
}
while (mach) {
// Get machine specific configuration file..
conf = conf_file_name(mach->file_name, base_path, conf_path);
if (conf == NULL) {
err = LIBUSB_ERROR_OTHER;
break;
}
p_id = parse_conf(conf);
if (!p_id) {
err = LIBUSB_ERROR_OTHER;
break;
}
p_id->ops->transfer = (p_id->mode == MODE_BULK) ? &transfer_bulk :
&transfer_hid;
curr = p_id->work;
// Prefer work from command line, disable batch mode...
if (cmd_head) {
curr = cmd_head;
mach->nextbatch = NULL;
}
if (curr == NULL) {
fprintf(stderr, "no job found\n");
err = LIBUSB_ERROR_OTHER;
break;
}
// Wait for device...
printf("Trying to open device vid=0x%04x pid=0x%04x", mach->vid, mach->pid);
fflush(stdout);
for (retry = 0; retry < 50; retry++) {
h = NULL;
err = libusb_open(dev, &h);
if (h)
break;
msleep(500);
if (retry % 2)
printf(".");
fflush(stdout);
}
printf("\n");
if (!h) {
err = LIBUSB_ERROR_NO_DEVICE;
fprintf(stderr, "Could not open device vid=0x%04x pid=0x%04x\n",
mach->vid, mach->pid);
break;
}
// USB private pointer is libusb device handle...
p_id->priv = h;
libusb_get_configuration(h, &config);
dbg_printf("bConfigurationValue = 0x%x\n", config);
if (libusb_kernel_driver_active(h, 0))
libusb_detach_kernel_driver(h, 0);
err = libusb_claim_interface(h, 0);
if (err) {
fprintf(stderr, "claim interface failed\n");
break;
}
printf("Interface 0 claimed\n");
err = do_work(p_id, &curr, verify);
dbg_printf("do_work finished with err=%d, curr=%p\n", err, curr);
libusb_release_interface(h, 0);
libusb_close(h);
if (err)
break;
// We might have to retry the same machine in case of plugin...
if (!curr)
mach = mach->nextbatch;
}
libusb_free_device_list(devs, 1);
out_deinit_usb:
libusb_exit(NULL);
return err;
}
static const struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"debugmode", no_argument, 0, 'd' },
{"verify", no_argument, 0, 'v' },
{"version", no_argument, 0, 'V' },
{"configdir", required_argument, 0, 'c' },
{"bus", required_argument, 0, 'b' },
{"device", required_argument, 0, 'D' },
{"sim", required_argument, 0, 'S' },
{0, 0, 0, 0 },
};
int main(int argc, char * const argv[])
{
int err, c;
int verify = 0;
struct sdp_work *cmd_head = NULL;
char const *conf;
char const *base_path = get_base_path(argv[0]);
char const *conf_path = get_global_conf_path();
char const *sim_vidpid = NULL;
int bus = -1;
int address = -1;
while ((c = getopt_long(argc, argv, "+hdvVc:b:D:S:", long_options, NULL)) != -1) {
switch (c)
{
case 'h':
case '?':
print_usage();
return EXIT_SUCCESS;
case 'd':
debugmode = 1; /* global extern */
break;
case 'v':
verify = 1;
break;
case 'V':
printf("imx_usb " IMX_LOADER_VERSION "\n");
return EXIT_SUCCESS;
case 'c':
conf_path = optarg;
break;
case 'b':
bus = atoi(optarg);
break;
case 'D':
address = atoi(optarg);
break;
case 'S':
sim_vidpid = optarg;
break;
}
}
if (optind < argc) {
// Parse optional job arguments...
cmd_head = parse_cmd_args(argc - optind, &argv[optind]);
}
// Get list of machines...
conf = conf_file_name("imx_usb.conf", base_path, conf_path);
if (conf == NULL)
return EXIT_FAILURE;
struct mach_id *list = parse_imx_conf(conf);
if (!list)
return EXIT_FAILURE;
if (sim_vidpid)
err = do_simulation_dev(base_path, conf_path, list, verify,
cmd_head, sim_vidpid);
else
err = do_autodetect_dev(base_path, conf_path, list, verify,
cmd_head, bus, address);
if (err < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
================================================
FILE: imx_usb.conf
================================================
#vid:pid, config_file
0x066f:0x3780, mx23_usb_work.conf
0x15a2:0x004f, mx28_usb_work.conf
0x15a2:0x0052, mx50_usb_work.conf
0x15a2:0x0054, mx6_usb_work.conf
0x15a2:0x0061, mx6_usb_work.conf
0x15a2:0x0063, mx6_usb_work.conf
0x15a2:0x0071, mx6_usb_work.conf
0x15a2:0x007d, mx6_usb_work.conf
0x15a2:0x0080, mx6ull_usb_work.conf
0x1fc9:0x0128, mx6_usb_work.conf
0x15a2:0x0076, mx7_usb_work.conf
0x1fc9:0x0126, mx7ulp_usb_work.conf
0x15a2:0x0041, mx51_usb_work.conf
0x15a2:0x004e, mx53_usb_work.conf
0x15a2:0x006a, vybrid_usb_work.conf
0x066f:0x37ff, linux_gadget.conf
0x1b67:0x4fff, mx6_usb_sdp_spl.conf
0x0525:0xb4a4, mx6_usb_sdp_spl.conf
0x1fc9:0x012b, mx8mq_usb_work.conf
0x1fc9:0x0134, mx8mm_usb_work.conf
0x1fc9:0x013e, mx8mn_usb_work.conf
0x3016:0x1001, mx8m_usb_sdp_spl.conf
================================================
FILE: msvc/getopt.c
================================================
/* Getopt for Microsoft C
This code is a modification of the Free Software Foundation, Inc.
Getopt library for parsing command line argument the purpose was
to provide a Microsoft Visual C friendly derivative. This code
provides functionality for both Unicode and Multibyte builds.
Date: 02/03/2011 - Ludvik Jerabek - Initial Release
Version: 1.0
Comment: Supports getopt, getopt_long, and getopt_long_only
and POSIXLY_CORRECT environment flag
License: LGPL
Revisions:
02/03/2011 - Ludvik Jerabek - Initial Release
02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
**DISCLAIMER**
THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include "getopt.h"
#ifdef __cplusplus
#define _GETOPT_THROW throw()
#else
#define _GETOPT_THROW
#endif
int optind = 1;
int opterr = 1;
int optopt = '?';
enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
//
//
// Ansi structures and functions follow
//
//
static struct _getopt_data_a
{
int optind;
int opterr;
int optopt;
char *optarg;
int __initialized;
char *__nextchar;
enum ENUM_ORDERING __ordering;
int __posixly_correct;
int __first_nonopt;
int __last_nonopt;
} getopt_data_a;
char *optarg_a;
static void exchange_a(char **argv, struct _getopt_data_a *d)
{
int bottom = d->__first_nonopt;
int middle = d->__last_nonopt;
int top = d->optind;
char *tem;
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
int len = middle - bottom;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
top -= len;
}
else
{
int len = top - middle;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
bottom += len;
}
}
d->__first_nonopt += (d->optind - d->__last_nonopt);
d->__last_nonopt = d->optind;
}
static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct)
{
d->__first_nonopt = d->__last_nonopt = d->optind;
d->__nextchar = NULL;
d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT");
if (optstring[0] == '-')
{
d->__ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
d->__ordering = REQUIRE_ORDER;
++optstring;
}
else if (d->__posixly_correct)
d->__ordering = REQUIRE_ORDER;
else
d->__ordering = PERMUTE;
return optstring;
}
int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct)
{
int print_errors = d->opterr;
if (argc < 1)
return -1;
d->optarg = NULL;
if (d->optind == 0 || !d->__initialized)
{
if (d->optind == 0)
d->optind = 1;
optstring = _getopt_initialize_a (optstring, d, posixly_correct);
d->__initialized = 1;
}
else if (optstring[0] == '-' || optstring[0] == '+')
optstring++;
if (optstring[0] == ':')
print_errors = 0;
if (d->__nextchar == NULL || *d->__nextchar == '\0')
{
if (d->__last_nonopt > d->optind)
d->__last_nonopt = d->optind;
if (d->__first_nonopt > d->optind)
d->__first_nonopt = d->optind;
if (d->__ordering == PERMUTE)
{
if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
exchange_a ((char **) argv, d);
else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
d->optind++;
d->__last_nonopt = d->optind;
}
if (d->optind != argc && !strcmp(argv[d->optind], "--"))
{
d->optind++;
if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
exchange_a((char **) argv, d);
else if (d->__first_nonopt == d->__last_nonopt)
d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
d->optind = argc;
}
if (d->optind == argc)
{
if (d->__first_nonopt != d->__last_nonopt)
d->optind = d->__first_nonopt;
return -1;
}
if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
{
if (d->__ordering == REQUIRE_ORDER)
return -1;
d->optarg = argv[d->optind++];
return 1;
}
d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-'));
}
if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1])))))
{
char *nameend;
unsigned int namelen;
const struct option_a *p;
const struct option_a *pfound = NULL;
struct option_list
{
const struct option_a *p;
struct option_list *next;
} *ambig_list = NULL;
int exact = 0;
int indfound = -1;
int option_index;
for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++);
namelen = (unsigned int)(nameend - d->__nextchar);
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp(p->name, d->__nextchar, namelen))
{
if (namelen == (unsigned int)strlen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
{
struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
newp->p = p;
newp->next = ambig_list;
ambig_list = newp;
}
}
if (ambig_list != NULL && !exact)
{
if (print_errors)
{
struct option_list first;
first.p = pfound;
first.next = ambig_list;
ambig_list = &first;
fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
do
{
fprintf (stderr, " '--%s'", ambig_list->p->name);
ambig_list = ambig_list->next;
}
while (ambig_list != NULL);
fputc ('\n', stderr);
}
d->__nextchar += strlen(d->__nextchar);
d->optind++;
d->optopt = 0;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
d->optind++;
if (*nameend)
{
if (pfound->has_arg)
d->optarg = nameend + 1;
else
{
if (print_errors)
{
if (argv[d->optind - 1][1] == '-')
{
fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
}
else
{
fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
}
}
d->__nextchar += strlen(d->__nextchar);
d->optopt = pfound->val;
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
}
d->__nextchar += strlen(d->__nextchar);
d->optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?';
}
}
d->__nextchar += strlen(d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL)
{
if (print_errors)
{
if (argv[d->optind][1] == '-')
{
fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
}
else
{
fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
}
}
d->__nextchar = (char *)"";
d->optind++;
d->optopt = 0;
return '?';
}
}
{
char c = *d->__nextchar++;
char *temp = (char*)strchr(optstring, c);
if (*d->__nextchar == '\0')
++d->optind;
if (temp == NULL || c == ':' || c == ';')
{
if (print_errors)
{
fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c);
}
d->optopt = c;
return '?';
}
if (temp[0] == 'W' && temp[1] == ';')
{
char *nameend;
const struct option_a *p;
const struct option_a *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = 0;
int option_index;
if (longopts == NULL)
goto no_longs;
if (*d->__nextchar != '\0')
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
}
d->optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
return c;
}
else
d->optarg = argv[d->optind++];
for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++);
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
ambig = 1;
}
if (ambig && !exact)
{
if (print_errors)
{
fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
}
d->__nextchar += strlen(d->__nextchar);
d->optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
if (*nameend)
{
if (pfound->has_arg)
d->optarg = nameend + 1;
else
{
if (print_errors)
{
fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
}
d->__nextchar += strlen(d->__nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
}
d->__nextchar += strlen(d->__nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
else
d->optarg = NULL;
d->__nextchar += strlen(d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
no_longs:
d->__nextchar = NULL;
return 'W';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
if (*d->__nextchar != '\0')
{
d->optarg = d->__nextchar;
d->optind++;
}
else
d->optarg = NULL;
d->__nextchar = NULL;
}
else
{
if (*d->__nextchar != '\0')
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
}
d->optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
d->optarg = argv[d->optind++];
d->__nextchar = NULL;
}
}
return c;
}
}
int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct)
{
int result;
getopt_data_a.optind = optind;
getopt_data_a.opterr = opterr;
result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct);
optind = getopt_data_a.optind;
optarg_a = getopt_data_a.optarg;
optopt = getopt_data_a.optopt;
return result;
}
int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW
{
return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0);
}
int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
{
return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0);
}
int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
{
return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0);
}
int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
{
return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0);
}
int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
{
return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0);
}
//
//
// Unicode Structures and Functions
//
//
static struct _getopt_data_w
{
int optind;
int opterr;
int optopt;
wchar_t *optarg;
int __initialized;
wchar_t *__nextchar;
enum ENUM_ORDERING __ordering;
int __posixly_correct;
int __first_nonopt;
int __last_nonopt;
} getopt_data_w;
wchar_t *optarg_w;
static void exchange_w(wchar_t **argv, struct _getopt_data_w *d)
{
int bottom = d->__first_nonopt;
int middle = d->__last_nonopt;
int top = d->optind;
wchar_t *tem;
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
int len = middle - bottom;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
top -= len;
}
else
{
int len = top - middle;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
bottom += len;
}
}
d->__first_nonopt += (d->optind - d->__last_nonopt);
d->__last_nonopt = d->optind;
}
static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct)
{
d->__first_nonopt = d->__last_nonopt = d->optind;
d->__nextchar = NULL;
d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT");
if (optstring[0] == L'-')
{
d->__ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == L'+')
{
d->__ordering = REQUIRE_ORDER;
++optstring;
}
else if (d->__posixly_correct)
d->__ordering = REQUIRE_ORDER;
else
d->__ordering = PERMUTE;
return optstring;
}
int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct)
{
int print_errors = d->opterr;
if (argc < 1)
return -1;
d->optarg = NULL;
if (d->optind == 0 || !d->__initialized)
{
if (d->optind == 0)
d->optind = 1;
optstring = _getopt_initialize_w (optstring, d, posixly_correct);
d->__initialized = 1;
}
else if (optstring[0] == L'-' || optstring[0] == L'+')
optstring++;
if (optstring[0] == L':')
print_errors = 0;
if (d->__nextchar == NULL || *d->__nextchar == L'\0')
{
if (d->__last_nonopt > d->optind)
d->__last_nonopt = d->optind;
if (d->__first_nonopt > d->optind)
d->__first_nonopt = d->optind;
if (d->__ordering == PERMUTE)
{
if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
exchange_w((wchar_t **) argv, d);
else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
d->optind++;
d->__last_nonopt = d->optind;
}
if (d->optind != argc && !wcscmp(argv[d->optind], L"--"))
{
d->optind++;
if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
exchange_w((wchar_t **) argv, d);
else if (d->__first_nonopt == d->__last_nonopt)
d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
d->optind = argc;
}
if (d->optind == argc)
{
if (d->__first_nonopt != d->__last_nonopt)
d->optind = d->__first_nonopt;
return -1;
}
if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
{
if (d->__ordering == REQUIRE_ORDER)
return -1;
d->optarg = argv[d->optind++];
return 1;
}
d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-'));
}
if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1])))))
{
wchar_t *nameend;
unsigned int namelen;
const struct option_w *p;
const struct option_w *pfound = NULL;
struct option_list
{
const struct option_w *p;
struct option_list *next;
} *ambig_list = NULL;
int exact = 0;
int indfound = -1;
int option_index;
for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++);
namelen = (unsigned int)(nameend - d->__nextchar);
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!wcsncmp(p->name, d->__nextchar, namelen))
{
if (namelen == (unsigned int)wcslen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
{
struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
newp->p = p;
newp->next = ambig_list;
ambig_list = newp;
}
}
if (ambig_list != NULL && !exact)
{
if (print_errors)
{
struct option_list first;
first.p = pfound;
first.next = ambig_list;
ambig_list = &first;
fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
do
{
fwprintf (stderr, L" '--%s'", ambig_list->p->name);
ambig_list = ambig_list->next;
}
while (ambig_list != NULL);
fputwc (L'\n', stderr);
}
d->__nextchar += wcslen(d->__nextchar);
d->optind++;
d->optopt = 0;
return L'?';
}
if (pfound != NULL)
{
option_index = indfound;
d->optind++;
if (*nameend)
{
if (pfound->has_arg)
d->optarg = nameend + 1;
else
{
if (print_errors)
{
if (argv[d->optind - 1][1] == L'-')
{
fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
}
else
{
fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
}
}
d->__nextchar += wcslen(d->__nextchar);
d->optopt = pfound->val;
return L'?';
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
}
d->__nextchar += wcslen(d->__nextchar);
d->optopt = pfound->val;
return optstring[0] == L':' ? L':' : L'?';
}
}
d->__nextchar += wcslen(d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL)
{
if (print_errors)
{
if (argv[d->optind][1] == L'-')
{
fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
}
else
{
fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
}
}
d->__nextchar = (wchar_t *)L"";
d->optind++;
d->optopt = 0;
return L'?';
}
}
{
wchar_t c = *d->__nextchar++;
wchar_t *temp = (wchar_t*)wcschr(optstring, c);
if (*d->__nextchar == L'\0')
++d->optind;
if (temp == NULL || c == L':' || c == L';')
{
if (print_errors)
{
fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c);
}
d->optopt = c;
return L'?';
}
if (temp[0] == L'W' && temp[1] == L';')
{
wchar_t *nameend;
const struct option_w *p;
const struct option_w *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = 0;
int option_index;
if (longopts == NULL)
goto no_longs;
if (*d->__nextchar != L'\0')
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c);
}
d->optopt = c;
if (optstring[0] == L':')
c = L':';
else
c = L'?';
return c;
}
else
d->optarg = argv[d->optind++];
for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++);
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
ambig = 1;
}
if (ambig && !exact)
{
if (print_errors)
{
fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
}
d->__nextchar += wcslen(d->__nextchar);
d->optind++;
return L'?';
}
if (pfound != NULL)
{
option_index = indfound;
if (*nameend)
{
if (pfound->has_arg)
d->optarg = nameend + 1;
else
{
if (print_errors)
{
fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
}
d->__nextchar += wcslen(d->__nextchar);
return L'?';
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
}
d->__nextchar += wcslen(d->__nextchar);
return optstring[0] == L':' ? L':' : L'?';
}
}
else
d->optarg = NULL;
d->__nextchar += wcslen(d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
no_longs:
d->__nextchar = NULL;
return L'W';
}
if (temp[1] == L':')
{
if (temp[2] == L':')
{
if (*d->__nextchar != L'\0')
{
d->optarg = d->__nextchar;
d->optind++;
}
else
d->optarg = NULL;
d->__nextchar = NULL;
}
else
{
if (*d->__nextchar != L'\0')
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c);
}
d->optopt = c;
if (optstring[0] == L':')
c = L':';
else
c = L'?';
}
else
d->optarg = argv[d->optind++];
d->__nextchar = NULL;
}
}
return c;
}
}
int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct)
{
int result;
getopt_data_w.optind = optind;
getopt_data_w.opterr = opterr;
result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct);
optind = getopt_data_w.optind;
optarg_w = getopt_data_w.optarg;
optopt = getopt_data_w.optopt;
return result;
}
int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW
{
return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0);
}
int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
{
return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0);
}
int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
{
return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0);
}
int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
{
return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0);
}
int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
{
return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0);
}
================================================
FILE: msvc/getopt.h
================================================
/* Getopt for Microsoft C
This code is a modification of the Free Software Foundation, Inc.
Getopt library for parsing command line argument the purpose was
to provide a Microsoft Visual C friendly derivative. This code
provides functionality for both Unicode and Multibyte builds.
Date: 02/03/2011 - Ludvik Jerabek - Initial Release
Version: 1.0
Comment: Supports getopt, getopt_long, and getopt_long_only
and POSIXLY_CORRECT environment flag
License: LGPL
Revisions:
02/03/2011 - Ludvik Jerabek - Initial Release
02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
**DISCLAIMER**
THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __GETOPT_H_
#define __GETOPT_H_
#ifdef _GETOPT_API
#undef _GETOPT_API
#endif
#if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
#error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually"
#elif defined(STATIC_GETOPT)
#pragma message("Warning static builds of getopt violate the Lesser GNU Public License")
#define _GETOPT_API
#elif defined(EXPORTS_GETOPT)
#pragma message("Exporting getopt library")
#define _GETOPT_API __declspec(dllexport)
#else
#pragma message("Importing getopt library")
#define _GETOPT_API __declspec(dllimport)
#endif
// Change behavior for C\C++
#ifdef __cplusplus
#define _BEGIN_EXTERN_C extern "C" {
#define _END_EXTERN_C }
#define _GETOPT_THROW throw()
#else
#define _BEGIN_EXTERN_C
#define _END_EXTERN_C
#define _GETOPT_THROW
#endif
// Standard GNU options
#define null_argument 0 /*Argument Null*/
#define no_argument 0 /*Argument Switch Only*/
#define required_argument 1 /*Argument Required*/
#define optional_argument 2 /*Argument Optional*/
// Shorter Options
#define ARG_NULL 0 /*Argument Null*/
#define ARG_NONE 0 /*Argument Switch Only*/
#define ARG_REQ 1 /*Argument Required*/
#define ARG_OPT 2 /*Argument Optional*/
#include <string.h>
#include <wchar.h>
_BEGIN_EXTERN_C
extern _GETOPT_API int optind;
extern _GETOPT_API int opterr;
extern _GETOPT_API int optopt;
// Ansi
struct option_a
{
const char* name;
int has_arg;
int *flag;
char val;
};
extern _GETOPT_API char *optarg_a;
extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW;
// Unicode
struct option_w
{
const wchar_t* name;
int has_arg;
int *flag;
wchar_t val;
};
extern _GETOPT_API wchar_t *optarg_w;
extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW;
_END_EXTERN_C
#undef _BEGIN_EXTERN_C
#undef _END_EXTERN_C
#undef _GETOPT_THROW
#undef _GETOPT_API
#ifdef _UNICODE
#define getopt getopt_w
#define getopt_long getopt_long_w
#define getopt_long_only getopt_long_only_w
#define option option_w
#define optarg optarg_w
#else
#define getopt getopt_a
#define getopt_long getopt_long_a
#define getopt_long_only getopt_long_only_a
#define option option_a
#define optarg optarg_a
#endif
#endif // __GETOPT_H_
================================================
FILE: msvc/imx_loader.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imx_uart", "imx_uart.vcxproj", "{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imx_usb", "imx_usb.vcxproj", "{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}.Debug|Win32.ActiveCfg = Debug|Win32
{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}.Debug|Win32.Build.0 = Debug|Win32
{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}.Debug|x64.ActiveCfg = Debug|Win32
{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}.Release|Win32.ActiveCfg = Release|Win32
{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}.Release|Win32.Build.0 = Release|Win32
{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}.Release|x64.ActiveCfg = Release|Win32
{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}.Debug|Win32.ActiveCfg = Debug|Win32
{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}.Debug|Win32.Build.0 = Debug|Win32
{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}.Debug|x64.ActiveCfg = Debug|Win32
{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}.Release|Win32.ActiveCfg = Release|Win32
{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}.Release|Win32.Build.0 = Release|Win32
{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
================================================
FILE: msvc/imx_uart.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E97E957F-CB34-4A96-B2AF-D2E7D902B27E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>imx_loaderuart_loader</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>imx_uart</TargetName>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(MSBuildProjectDirectory)</IncludePath>
<OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>imx_uart</TargetName>
<OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;STATIC_GETOPT;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<UndefinePreprocessorDefinitions>_UNICODE</UndefinePreprocessorDefinitions>
<AdditionalIncludeDirectories>$(MSBuildProjectDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;STATIC_GETOPT;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<UndefinePreprocessorDefinitions>_UNICODE</UndefinePreprocessorDefinitions>
<AdditionalIncludeDirectories>$(MSBuildProjectDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\imx_loader_config.c" />
<ClCompile Include="..\imx_sdp.c" />
<ClCompile Include="..\imx_uart.c" />
<ClCompile Include="getopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\imx_loader_config.h" />
<ClInclude Include="..\imx_sdp.h" />
<ClInclude Include="..\portable.h" />
<ClInclude Include="getopt.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\vybrid_usb_work.conf" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
================================================
FILE: msvc/imx_usb.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1D2B783C-E033-49B3-ACD1-8AA3C5A51774}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>imx_loaderuart_loader</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>imx_usb</TargetName>
<OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>imx_usb</TargetName>
<OutDir>$(SolutionDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;STATIC_GETOPT;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<UndefinePreprocessorDefinitions>_UNICODE</UndefinePreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\libusb\include;$(MSBuildProjectDirectory)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\libusb\MS32\dll\</AdditionalLibraryDirectories>
<AdditionalDependencies>libusb-1.0.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>IMXCONFDIR=$(APPDATA)\imx_loader\;WIN32;STATIC_GETOPT;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<UndefinePreprocessorDefinitions>_UNICODE</UndefinePreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\libusb\include;$(MSBuildProjectDirectory)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>libusb-1.0.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\libusb\MS32\dll\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\imx_loader_config.c" />
<ClCompile Include="..\imx_sdp_simulation.c" />
<ClCompile Include="..\imx_sdp.c" />
<ClCompile Include="..\imx_usb.c" />
<ClCompile Include="getopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\imx_loader_config.h" />
<ClInclude Include="..\imx_sdp_simulation.h" />
<ClInclude Include="..\imx_sdp.h" />
<ClInclude Include="..\portable.h" />
<ClInclude Include="getopt.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\vybrid_usb_work.conf" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
================================================
FILE: mx50_usb_work.conf
================================================
mx50
#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)
hid,64,0xf8006400,0xf8006400,128M
#file:dcd,plug,load nnn,jump [nnn/header/header2]
#jump nnn - new header is placed after last downloaded word
# entire file is loaded before jump, needs load nnn as well
# i.e. file:load nnn,jump nnn
#jump header - only length parameter is downloaded
# header - uses existing header(error if none), but clears plug and dcd values unless plug also specified
# header2 - uses 2nd header found(error if none)
#plug - without jump uses header but clears plug flag to stop after plug execution
SPL:dcd
u-boot.bin:load 0x77800000
SPL:load 0xF8006400, jump header
================================================
FILE: mx51_usb_work.conf
================================================
mx51
#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)
bulk,old_header,64,0x1ffe2000,0x90000000,512M,0x1ffe2000,0x16000
#file:dcd,plug,load nnn,jump [nnn/header/header2]
#jump nnn - new header is placed after last downloaded word
# entire file is loaded before jump, needs load nnn as well
# i.e. file:load nnn,jump nnn
#jump header - only length parameter is downloaded
# header - uses existing header(error if none), but clears plug and dcd values unless plug also specified
# header2 - uses 2nd header found(error if none)
#plug - without jump uses header but clears plug flag to stop after plug execution
#../u-boot-watchie/u-boot.bin:dcd,plug,jump header
../imx_utils/mx51_ddr_init_xm.bin:dcd,plug,jump header
../u-boot-watchie/mx51_ubl_ecspi.bin:load 0x93f00000
../imx_utils/mx51_ecspi_ram_write_xm.bin:dcd,plug,jump header
================================================
FILE: mx53_usb_work.conf
================================================
mx53
#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)
bulk,512,0xf8006000,0x70000000,512M,0xf8006000,0x12000
#file:dcd,plug,load nnn,jump [nnn/header/header2]
#jump nnn - new header is placed after last downloaded word
# entire file is loaded before jump, needs load nnn as well
# i.e. file:load nnn,jump nnn
#jump header - only length parameter is downloaded
# header - uses existing header(error if none), but clears plug and dcd values unless plug also specified
# header2 - uses 2nd header found(error if none)
#plug - without jump uses header but clears plug flag to stop after plug execution
#../u-boot-watchie/u-boot.bin:dcd,plug,jump header
../imx_utils/mx53_ddr_init_xm.bin:dcd,plug
../u-boot-watchie/mx53_ubl_ecspi.bin:load 0x73f00000
../imx_utils/mx53_ecspi_ram_write_xm.bin:jump header2
================================================
FILE: mx6_usb_sdp_spl.conf
================================================
mx6_spl_sdp
#hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat valid ram areas)
#In SPL, we typically load u-boot.img which has a U-boot header...
hid,uboot_header,1024,0x10000000,1G,0x00907000,0x31000
================================================
FILE: mx6_usb_work.conf
================================================
mx6_qsb
#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)
hid,1024,0x910000,0x10000000,1G,0x00900000,0x40000
#file:dcd,plug,load nnn,jump [nnn/header/header2]
#jump nnn - header is after last downloaded word
# entire file is loaded before jump, needs load nnn as well
# i.e. file:load nnn,jump nnn
#jump header - only length parameter is downloaded
# header - uses existing header(error if none), but clears plug and dcd values unless plug also specified
# header2 - uses 2nd header found(error if none)
#jump_direct nnn - nnn is address of header or script commands
# This does not build a header like jump nnn will.
#plug - without jump uses header but clears plug flag to stop after plug execution
#load nnn - load entire file to address
#size nnn - limit file size to load
#skip nnn - ignore the 1st nnn bytes from file
#../u-boot-imx6/u-boot.bin:dcd,plug,jump header
#:modify,020e02a8,7,1
#:modify,020e00bc,7,4
#:read,020e02a8
#:read,020e00bc
#:read,020c4078
#:modify,020c407c,0,0f000000
#:modify,020c4080,0,c00
#:read,020c4084
#../imx_utils/mx6_ddr_init_xm.bin:dcd
#../u-boot-imx6/u-boot.bin:load 0x13effc00
#../u-boot-imx6/u-boot.imx:load 0x13f00000
#../u-boot-dirk/u-boot.imx:load 0x13f00000
#u-boot-6w.bin:load 0x13effc00
#u-boot_1103.bin:load 0x13effc00
#u-boot_1103.bin:jump header
#../imx_utils/mx6_ecspi_ram_write_xm.bin:clear_dcd,plug
#../imx6_obds/output/mx61/bin/diag-obds-mx61qsb-rev1.bin:jump header
================================================
FILE: mx6ull_usb_work.conf
================================================
mx6ull
#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)
hid,1024,0x910000,0x80000000,2G,0x00900000,0x20000
#../u-boot-imx6/u-boot.imx:dcd
#../u-boot-imx6/u-boot.imx:load 0x83f00000
#../imx_utils/mx6_ecspi_ram_write_xm.bin:clear_dcd,plug
================================================
FILE: mx7_usb_work.conf
================================================
mx7
#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)
hid,1024,0x910000,0x80000000,1G,0x00900000,0x20000
#file:dcd,plug,load nnn,jump [nnn/header/header2]
#jump nnn - header is after last downloaded word
# entire file is loaded before jump, needs load nnn as well
# i.e. file:load nnn,jump nnn
#jump header - only length parameter is downloaded
#header - uses existing header(error if none), but clears plug and dcd values unless plug also specified
#header2 - uses 2nd header found(error if none)
#plug - without jump uses header but clears plug flag to stop after plug execution
#load nnn - load entire file to address
#../u-boot-imx6/u-boot.bin:dcd,plug,jump header
#:modify,020e02a8,7,1
#:modify,020e00bc,7,4
#:read,020e02a8
#:read,020e00bc
#:read,020c4078
#:modify,020c407c,0,0f000000
#:modify,020c4080,0,c00
#:read,020c4084
#../imx_utils/mx6_ddr_init_xm.bin:dcd
#../u-boot-imx6/u-boot.bin:load 0x13effc00
#../u-boot-imx6/u-boot.imx:load 0x13f00000
#../u-boot-dirk/u-boot.imx:load 0x13f00000
#u-boot-6w.bin:load 0x13effc00
#u-boot_1103.bin:load 0x13effc00
#u-boot_1103.bin:jump header
#../imx_utils/mx6_ecspi_ram_write_xm.bin:clear_dcd,plug
#../imx6_obds/output/mx61/bin/diag-obds-mx61qsb-rev1.bin:jump header
================================================
FILE: mx7ulp_usb_work.conf
================================================
mx7ulp
#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)
hid,1024,0x2f020000,0x60000000,1G,0x900000,0x40000
================================================
FILE: mx8m_usb_sdp_spl.conf
================================================
mx8m_spl_sdp
#hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat valid ram areas)
#In SPL, we typically load u-boot.img which has a U-boot header...
hid,1024,0x910000,0x40000000,1G,0x00900000,0x40000
#0x60000 - 0x8400 = 0x57c00, +0x3000=5ac00 (FIT image)
../u-boot-imx6/u-boot.bin:load 0x40200000
# Uncomment the line below for i.MX8MQ platforms
../u-boot-imx6/bl31-iMX8MQ.bin:load 0x00910000,jump 0x910000
# Uncomment the line below for i.MX8MM platforms
#../u-boot-imx6/bl31-iMX8MM.bin:load 0x00920000,jump 0x920000
# Uncomment the line below for i.MX8MN platforms
#../u-boot-imx6/bl31-iMX8MN.bin:load 0x00960000,jump 0x960000
================================================
FILE: mx8mm_usb_work.conf
================================================
mx8mm_qsb
#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)
hid,1024,0x910000,0x40000000,1G,0x00900000,0x40000
#load/run SPL
../u-boot-imx6/flash.bin:dcd,clear_dcd,plug,jump header
================================================
FILE: mx8mn_usb_work.conf
================================================
mx8mn
#hid/bulk/sdps,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)
sdps,no-hid-cmd,ep1,1020,0x910000,0x40000000,1G,0x00900000,0x40000
#load/run SPL
../u-boot-imx6/flash.bin:dcd,clear_dcd,plug,jump header
================================================
FILE: mx8mq_usb_work.conf
================================================
mx8_qsb
#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)
hid,1024,0x910000,0x40000000,1G,0x00900000,0x40000
#load/run SPL
../u-boot-imx6/flash.bin:dcd,clear_dcd,plug,jump header
#0x60000 - 0x8400 = 0x57c00, +0x3000=5ac00 (FIT image)
#../u-boot-imx6/u-boot.bin:load 0x40200000
#../u-boot-imx6/bl31-iMX8MQ.bin:load 0x00910000,jump 0x910000
================================================
FILE: portable.h
================================================
#ifndef __PORTABLE_H__
#define __PORTABLE_H__
extern int debugmode;
#ifndef WIN32
#define dbg_printf(fmt, args...) do{ if(debugmode) fprintf(stderr, fmt, ## args); } while(0)
#define dbg_dump_long(src, cnt, addr, skip) do{ if(debugmode) dump_long(src, cnt, addr, skip); } while(0)
#else
#ifdef DEBUG
#define dbg_printf(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#define dbg_dump_long(src, cnt, addr, skip) dump_long(src, cnt, addr, skip)
#else
#define dbg_dump_long(src, cnt, addr, skip)
#define dbg_printf(fmt, ...) /* Don't do anything in release builds */
#endif
#endif
#ifndef _MSC_VER
#include <unistd.h>
#endif
#ifdef WIN32
#include <Windows.h>
#include <direct.h>
#include <io.h>
#endif
#ifdef __linux__
#include <linux/limits.h>
#endif
#ifdef __APPLE__
#include <sys/syslimits.h>
#endif
#ifdef __FreeBSD__
#include <sys/param.h>
#endif
#ifndef WIN32
#define PATH_SEPARATOR '/'
#define msleep(ms) usleep((ms) * 1000)
#else
#define PATH_MAX MAX_PATH
#define PATH_SEPARATOR '\\'
#define msleep(ms) Sleep(ms)
#endif
#ifdef _MSC_VER
#define R_OK 04
#define open(filename,oflag) _open(filename,oflag)
#define write(fd,buffer,count) _write(fd,buffer,count)
#define read(fd,buffer,count) _read(fd,buffer,count)
#define close(fd) _close(fd)
#define access(filename,oflag) _access(filename,oflag)
#define getcwd(buffer, maxlen) _getcwd(buffer, maxlen)
#endif
#ifdef __GNUC__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define BE32(x) __builtin_bswap32(x)
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))
#define BE16(x) __builtin_bswap16(x)
#else
#define BE16(x) \
({ \
typeof(x) __x = (x); \
(((__x << 8) & 0xffff) | ((__x >> 8) & 0xff)); \
})
#endif
#else
#define BE32(x) x
#define BE16(x) x
#endif
#elif _MSC_VER // assume little endian...
#define BE32(x) _byteswap_ulong(x)
#define BE16(x) _byteswap_ushort(x)
#endif
#endif /* __PORTABLE_H__ */
================================================
FILE: sdp.c
================================================
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include "imx_sdp.h"
#include "portable.h"
#pragma pack (1)
struct sdp_command {
uint16_t cmd;
uint32_t addr;
uint8_t format;
uint32_t cnt;
uint32_t data;
uint8_t rsvd;
};
#pragma pack ()
#define SDP_READ_REG 0x0101
#define SDP_WRITE_REG 0x0202
#define SDP_WRITE_FILE 0x0404
#define SDP_ERROR_STATUS 0x0505
#define SDP_WRITE_DCD 0x0a0a
#define SDP_JUMP_ADDRESS 0x0b0b
static int sdp_fill_read_reg(unsigned char *buf, unsigned addr, unsigned cnt)
{
struct sdp_command read_reg_command = {
.cmd = SDP_READ_REG,
.addr = BE32(addr),
.format = 0x20,
.cnt = BE32(cnt),
.data = BE32(0),
.rsvd = 0x00
};
int cmd_size = sizeof(struct sdp_command);
memcpy(buf, &read_reg_command, cmd_size);
return cmd_size;
}
static int sdp_fill_write_reg(unsigned char *buf, unsigned addr, unsigned val)
{
struct sdp_command write_reg_command = {
.cmd = SDP_WRITE_REG,
.addr = BE32(addr),
.format = 0x20,
.cnt = BE32(4),
.data = BE32(val),
.rsvd = 0x00
};
int cmd_size = sizeof(struct sdp_command);
memcpy(buf, &write_reg_command, cmd_size);
return cmd_size;
}
static int sdp_fill_status(unsigned char *buf)
{
struct sdp_command status_command = {
.cmd = SDP_ERROR_STATUS,
.addr = 0,
.format = 0,
.cnt = 0,
.data = 0,
.rsvd = 0
};
int cmd_size = sizeof(struct sdp_command);
memcpy(buf, &status_command, cmd_size);
return cmd_size;
}
static int sdp_fill_dl_dcd(unsigned char *buf, unsigned dcd_addr, int length)
{
struct sdp_command dl_command = {
.cmd = SDP_WRITE_DCD,
.addr = BE32(dcd_addr),
.format = 0,
.cnt = BE32(length),
.data = 0,
.rsvd = 0
};
int cmd_size = sizeof(struct sdp_command);
memcpy(buf, &dl_command, cmd_size);
return cmd_size;
}
static int sdp_fill_write_file(unsigned char *buf, unsigned dladdr, unsigned fsize, unsigned char type)
{
struct sdp_command dl_command = {
.cmd = SDP_WRITE_FILE,
.addr = BE32(dladdr),
.format = 0,
.cnt = BE32(fsize),
.data = 0,
.rsvd = type
};
int cmd_size = sizeof(struct sdp_command);
memcpy(buf, &dl_command, cmd_size);
return cmd_size;
}
static int sdp_fill_jump(unsigned char *buf, unsigned header_addr)
{
struct sdp_command jump_command = {
.cmd = SDP_JUMP_ADDRESS,
.addr = BE32(header_addr),
.format = 0,
.cnt = 0,
.data = 0,
.rsvd = 0x00
};
int cmd_size = sizeof(struct sdp_command);
memcpy(buf, &jump_command, cmd_size);
return cmd_size;
}
static int sdp_get_cmd_addr_cnt(unsigned char *buf,
uint16_t *cmd, uint32_t *addr, uint32_t *cnt)
{
struct sdp_command *p = (struct sdp_command *)buf;
uint16_t c = p->cmd;
uint16_t tc = CMD_INVAL;
switch (c) {
case SDP_READ_REG:
tc = CMD_READ_REG;
break;
case SDP_WRITE_REG:
tc = CMD_WRITE_REG;
break;
case SDP_WRITE_FILE:
tc = CMD_WRITE_FILE;
break;
case SDP_ERROR_STATUS:
tc = CMD_ERROR_STATUS;
break;
case SDP_WRITE_DCD:
tc = CMD_WRITE_DCD;
break;
case SDP_JUMP_ADDRESS:
tc = CMD_JUMP_ADDRESS;
break;
}
*cmd = tc;
*addr = BE32(p->addr);
*cnt = BE32(p->cnt);
return sizeof(struct sdp_command);
}
static struct protocol_ops sdp_protocol_ops = {
.fill_read_reg = sdp_fill_read_reg,
.fill_write_reg = sdp_fill_write_reg,
.fill_status = sdp_fill_status,
.fill_dl_dcd = sdp_fill_dl_dcd,
.fill_write_file = sdp_fill_write_file,
.fill_jump = sdp_fill_jump,
.get_cmd_addr_cnt = sdp_get_cmd_addr_cnt,
};
void sdp_init_ops(struct sdp_dev *dev)
{
dev->ops = &sdp_protocol_ops;
}
================================================
FILE: sdp.h
================================================
void sdp_init_ops(struct sdp_dev *dev);
================================================
FILE: sdps.c
================================================
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include "imx_sdp.h"
#include "portable.h"
#pragma pack (1)
struct spds
{
unsigned signature; // Signature: 0x43544C42:1129598018, o "BLTC" (little endian) for the BLTC CBW
unsigned tag; // Tag: to be returned in the csw
unsigned xfer_length; // XferLength: number of bytes to transfer
unsigned char flags; // Flags:
// Bit 7: direction - device shall ignore this bit if the
// XferLength field is zero, otherwise:
// 0 = data-out from the host to the device,
// 1 = data-in from the device to the host.
// Bits 6..0: reserved - shall be zero.
unsigned char reserved[2]; // Reserved - shall be zero.
unsigned char command;
unsigned length;
unsigned char reserved2[11];
};
#pragma pack ()
static int sdps_fill_read_reg(unsigned char *buf, unsigned addr, unsigned cnt)
{
return 0;
}
static int sdps_fill_write_reg(unsigned char *buf, unsigned addr, unsigned cnt)
{
return 0;
}
static int sdps_fill_status(unsigned char *buf)
{
return 0;
}
static int sdps_fill_dl_dcd(unsigned char *buf, unsigned dcd_addr, int length)
{
return 0;
}
static int sdps_fill_write_file(unsigned char *buf, unsigned dladdr, unsigned fsize, unsigned char type)
{
struct spds dl_command = {
.signature = 0x43544C42, /* "BLTC" */
.tag = 1,
.xfer_length = fsize,
.flags = 0, /* Data In to device */
.command = 2, /* download firmware */
.length = BE32(fsize),
};
int cmd_size = sizeof(struct spds);
memcpy(buf, &dl_command, cmd_size);
return cmd_size;
}
static int sdps_fill_jump(unsigned char *buf, unsigned header_addr)
{
return 0;
}
static struct protocol_ops sdps_protocol_ops = {
.fill_read_reg = sdps_fill_read_reg,
.fill_write_reg = sdps_fill_write_reg,
.fill_status = sdps_fill_status,
.fill_dl_dcd = sdps_fill_dl_dcd,
.fill_write_file = sdps_fill_write_file,
.fill_jump = sdps_fill_jump,
};
void sdps_init_ops(struct sdp_dev *dev)
{
dev->ops = &sdps_protocol_ops;
}
================================================
FILE: sdps.h
================================================
void sdps_init_ops(struct sdp_dev *dev);
================================================
FILE: tests/Makefile
================================================
IMX_USB ?= ../imx_usb
%.test: % FORCE
@echo Testing $*
@$(IMX_USB) -v -S 0x15a2:0x0061 $* > $@
@diff -u $*.output $@
tests: test.imx.test test-dcd.imx.test test-plugin.imx.test
%.output: % FORCE
$(IMX_USB) -v -S 0x15a2:0x0061 $* > $@
regen: test.imx.output test-dcd.imx.output test-plugin.imx.output
FORCE: ;
.PHONY: tests regen
================================================
FILE: tests/bare.cfg
================================================
IMAGE_VERSION 2
BOOT_FROM sd
================================================
FILE: tests/create.txt
================================================
=> IMX image with plugin
mkimage -n plugin.cfg -T imximage -a -e 0x87800000 -d image.bin test-plugin.imx
=> IMX image without plugin
mkimage -n noplugin.cfg -T imximage -e 0x87800000 -d image.bin test.imx
=> IMX image with DCD
mkimage -n dcd.cfg -T imximage -e 0x87800000 -d image.bin test-dcd.imx
================================================
FILE: tests/dcd.cfg
================================================
IMAGE_VERSION 2
BOOT_FROM sd
DATA 4 0x30000000 0x12345678
================================================
FILE: tests/plugin.cfg
================================================
IMAGE_VERSION 2
BOOT_FROM sd
PLUGIN plugin.bin 0x00907000
================================================
FILE: tests/test-dcd.imx.output
================================================
config file <..//imx_usb.conf>
vid=0x066f pid=0x3780 file_name=mx23_usb_work.conf
vid=0x15a2 pid=0x004f file_name=mx28_usb_work.conf
vid=0x15a2 pid=0x0052 file_name=mx50_usb_work.conf
vid=0x15a2 pid=0x0054 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0061 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0063 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0071 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x007d file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0080 file_name=mx6ull_usb_work.conf
vid=0x1fc9 pid=0x0128 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0076 file_name=mx7_usb_work.conf
vid=0x1fc9 pid=0x0126 file_name=mx7ulp_usb_work.conf
vid=0x15a2 pid=0x0041 file_name=mx51_usb_work.conf
vid=0x15a2 pid=0x004e file_name=mx53_usb_work.conf
vid=0x15a2 pid=0x006a file_name=vybrid_usb_work.conf
vid=0x066f pid=0x37ff file_name=linux_gadget.conf
vid=0x1b67 pid=0x4fff file_name=mx6_usb_sdp_spl.conf
vid=0x0525 pid=0xb4a4 file_name=mx6_usb_sdp_spl.conf
vid=0x1fc9 pid=0x012b file_name=mx8mq_usb_work.conf
vid=0x1fc9 pid=0x0134 file_name=mx8mm_usb_work.conf
vid=0x1fc9 pid=0x013e file_name=mx8mn_usb_work.conf
vid=0x3016 pid=0x1001 file_name=mx8m_usb_sdp_spl.conf
Simulating with vid=0x15a2 pid=0x0061
config file <..//mx6_usb_work.conf>
parse ..//mx6_usb_work.conf
report=1, cnt=16
00000000: 05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00
cmd: 0505
report=3, cnt=64
HAB security state: development mode (0x56787856)
report=4, cnt=64
== work item
filename test-dcd.imx
load_size 0 bytes
load_addr 0x00000000
dcd 1
clear_dcd 0
plug 1
jump_mode 3
jump_addr 0x00000000
== end work item
loading DCD table @0x910000
report=1, cnt=16
00000000: 0a 0a 00 91 00 00 00 00 00 00 10 00 00 00 00 00
cmd: 0a0a
report=2, cnt=16
00000000: d2 00 10 40 cc 00 0c 04 30 00 00 00 12 34 56 78
<<<16, 16 bytes>>>
report=3, cnt=64
report=4, cnt=64
succeeded (security 0x56787856, status 0x128a8a12)
clear dcd_ptr=0x877ff42c
loading binary file(test-dcd.imx) to 877ff400, skip=0, fsize=1c00 type=aa
report=1, cnt=16
00000000: 04 04 87 7f f4 00 00 00 00 1c 00 00 00 00 00 aa
cmd: 0404
report=2, cnt=1024
00000000: d1 00 20 40 00 00 80 87 00 00 00 00 00 00 00 00
00000010: 20 f4 7f 87 00 f4 7f 87 00 00 00 00 00 00 00 00
00000020: 00 f0 7f 87 00 20 00 00 00 00 00 00 d2 00 10 40
00000030: cc 00 0c 04 30 00 00 00 12 34 56 78 00 00 00 00
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
report=2, cnt=1024
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001b0: 00 0
gitextract_fml__pjx/ ├── .gitignore ├── COPYING ├── Makefile ├── Makefile.mingw ├── README.md ├── image.h ├── imx_loader.h ├── imx_loader_config.c ├── imx_loader_config.h ├── imx_sdp.c ├── imx_sdp.h ├── imx_sdp_simulation.c ├── imx_sdp_simulation.h ├── imx_uart.c ├── imx_usb.c ├── imx_usb.conf ├── msvc/ │ ├── getopt.c │ ├── getopt.h │ ├── imx_loader.sln │ ├── imx_uart.vcxproj │ └── imx_usb.vcxproj ├── mx50_usb_work.conf ├── mx51_usb_work.conf ├── mx53_usb_work.conf ├── mx6_usb_sdp_spl.conf ├── mx6_usb_work.conf ├── mx6ull_usb_work.conf ├── mx7_usb_work.conf ├── mx7ulp_usb_work.conf ├── mx8m_usb_sdp_spl.conf ├── mx8mm_usb_work.conf ├── mx8mn_usb_work.conf ├── mx8mq_usb_work.conf ├── portable.h ├── sdp.c ├── sdp.h ├── sdps.c ├── sdps.h ├── tests/ │ ├── Makefile │ ├── bare.cfg │ ├── create.txt │ ├── dcd.cfg │ ├── plugin.cfg │ ├── test-dcd.imx.output │ ├── test-plugin.imx.output │ └── test.imx.output └── vybrid_usb_work.conf
SYMBOL INDEX (153 symbols across 15 files)
FILE: image.h
type __be32 (line 20) | typedef uint32_t __be32;
type image_header_t (line 202) | typedef struct image_header {
FILE: imx_loader_config.c
function get_val (line 31) | int get_val(const char** pp, int base)
function end_of_line (line 186) | int end_of_line(const char *p)
function parse_mem_work (line 195) | void parse_mem_work(struct sdp_work *curr, const char *filename, const c...
function parse_file_work (line 247) | void parse_file_work(struct sdp_work *curr, const char *filename, const ...
function parse_transfer_type (line 329) | void parse_transfer_type(struct sdp_dev *usb, const char *filename, cons...
type sdp_dev (line 396) | struct sdp_dev
type sdp_work (line 401) | struct sdp_work
type sdp_work (line 402) | struct sdp_work
type sdp_dev (line 403) | struct sdp_dev
type sdp_dev (line 403) | struct sdp_dev
type sdp_dev (line 403) | struct sdp_dev
type sdp_dev (line 406) | struct sdp_dev
type sdp_work (line 439) | struct sdp_work
type sdp_work (line 439) | struct sdp_work
type sdp_work (line 442) | struct sdp_work
type sdp_work (line 460) | struct sdp_work
type sdp_work (line 463) | struct sdp_work
type sdp_work (line 464) | struct sdp_work
type sdp_work (line 465) | struct sdp_work
type sdp_work (line 502) | struct sdp_work
type sdp_work (line 503) | struct sdp_work
FILE: imx_loader_config.h
type sdp_work (line 23) | struct sdp_work
type sdp_dev (line 31) | struct sdp_dev
type sdp_work (line 32) | struct sdp_work
FILE: imx_sdp.c
type load_desc (line 50) | struct load_desc {
type boot_data (line 71) | struct boot_data {
type ivt_header (line 86) | struct ivt_header {
type flash_header_v2 (line 93) | struct flash_header_v2 {
type write_dcd_command (line 105) | struct write_dcd_command {
type dcd_v2 (line 112) | struct dcd_v2 {
type flash_header_v1 (line 122) | struct flash_header_v1 {
function print_sdp_work (line 134) | static void print_sdp_work(struct sdp_work *curr)
function get_file_size (line 149) | static long get_file_size(FILE *xfile)
function do_response (line 159) | static int do_response(struct sdp_dev *dev, int report, unsigned int *re...
function do_command (line 183) | static int do_command(struct sdp_dev *dev, unsigned char *cmd, int cmd_s...
function read_memory (line 202) | static int read_memory(struct sdp_dev *dev, unsigned addr, unsigned char...
function write_memory (line 257) | static int write_memory(struct sdp_dev *dev, unsigned addr, unsigned val)
function perform_mem_work (line 289) | static void perform_mem_work(struct sdp_dev *dev, struct mem_work *mem)
function do_status (line 314) | static int do_status(struct sdp_dev *dev)
function do_data_transfer (line 354) | static int do_data_transfer(struct sdp_dev *dev, unsigned char *buf, int...
function write_dcd (line 402) | static int write_dcd(struct sdp_dev *dev, struct dcd_v2 *dcd)
function write_dcd_table_ivt (line 454) | static int write_dcd_table_ivt(struct sdp_dev *dev, struct dcd_v2 *dcdhdr)
function get_dcd_range_old (line 548) | static int get_dcd_range_old(struct flash_header_v1 *hdr,
function write_dcd_table_old (line 588) | static int write_dcd_table_old(struct sdp_dev *dev, struct flash_header_...
function diff_long (line 614) | static void diff_long(unsigned char *src1, unsigned char *src2, unsigned...
function dump_long (line 656) | void dump_long(unsigned char *src, unsigned cnt, unsigned addr, unsigned...
function dump_bytes (line 681) | void dump_bytes(unsigned char *src, unsigned cnt, unsigned addr)
function fetch_data (line 709) | static void fetch_data(struct load_desc *ld, unsigned foffset, unsigned ...
function verify_memory (line 734) | static int verify_memory(struct sdp_dev *dev, struct load_desc *ld, unsi...
function load_file (line 809) | static int load_file(struct sdp_dev *dev, struct load_desc *ld, unsigned...
function jump (line 901) | static int jump(struct sdp_dev *dev, unsigned int header_addr)
function load_file_from_desc (line 937) | static int load_file_from_desc(struct sdp_dev *dev, struct sdp_work *curr,
function is_header (line 1016) | static int is_header(struct sdp_dev *dev, unsigned char *p)
function init_header (line 1044) | static void init_header(struct sdp_dev *dev, struct load_desc *ld)
function perform_dcd (line 1105) | static int perform_dcd(struct sdp_dev *dev, unsigned char *p, unsigned c...
function clear_dcd_ptr (line 1173) | static int clear_dcd_ptr(struct sdp_dev *dev, unsigned char *p)
function get_dl_start (line 1198) | static int get_dl_start(struct sdp_dev *dev, unsigned char *p,
function process_header (line 1262) | static int process_header(struct sdp_dev *dev, struct sdp_work *curr,
function do_download (line 1362) | static int do_download(struct sdp_dev *dev, struct sdp_work *curr, int v...
function do_work (line 1440) | int do_work(struct sdp_dev *p_id, struct sdp_work **work, int verify)
FILE: imx_sdp.h
type ram_area (line 26) | struct ram_area {
type mem_work (line 31) | struct mem_work {
type sdp_work (line 40) | struct sdp_work
type sdp_work (line 41) | struct sdp_work {
type sdp_dev (line 60) | struct sdp_dev
type protocol_ops (line 62) | struct protocol_ops {
type sdp_dev (line 82) | struct sdp_dev {
type sdp_dev (line 124) | struct sdp_dev
type sdp_work (line 124) | struct sdp_work
FILE: imx_sdp_simulation.c
type sim_memory (line 29) | struct sim_memory
type sim_memory (line 30) | struct sim_memory {
function do_simulation (line 38) | int do_simulation(struct sdp_dev *dev, int report, unsigned char *p, uns...
function do_simulation_cleanup (line 139) | void do_simulation_cleanup(void)
FILE: imx_sdp_simulation.h
type sdp_dev (line 24) | struct sdp_dev
FILE: imx_uart.c
function transfer_uart (line 49) | int transfer_uart(struct sdp_dev *dev, int report, unsigned char *p, uns...
type termios (line 76) | struct termios
function uart_connect (line 78) | int uart_connect(int *uart_fd, char const *tty, int usertscts, int assoc...
type termios (line 242) | struct termios
function uart_close (line 244) | void uart_close(int *uart_fd, DCB* orig)
function print_usage (line 265) | void print_usage(void)
function parse_opts (line 292) | int parse_opts(int argc, char * const *argv, char const **ttyfile,
function sdps_init_ops (line 360) | void sdps_init_ops(struct sdp_dev *dev)
function main (line 368) | int main(int argc, char * const argv[])
FILE: imx_usb.c
type mach_id (line 44) | struct mach_id
type mach_id (line 45) | struct mach_id {
function print_devs (line 53) | static void print_devs(libusb_device **devs)
type mach_id (line 93) | struct mach_id
type mach_id (line 97) | struct mach_id
type mach_id (line 120) | struct mach_id
type mach_id (line 120) | struct mach_id
type mach_id (line 134) | struct mach_id
type mach_id (line 137) | struct mach_id
type mach_id (line 138) | struct mach_id
type mach_id (line 139) | struct mach_id
type mach_id (line 174) | struct mach_id
type mach_id (line 174) | struct mach_id
function libusb_device (line 186) | static libusb_device *find_imx_dev(libusb_device **devs, struct mach_id ...
function transfer_hid (line 245) | static int transfer_hid(struct sdp_dev *dev, int report, unsigned char *...
function transfer_bulk (line 322) | static int transfer_bulk(struct sdp_dev *dev, int report, unsigned char ...
function transfer_simulation (line 344) | int transfer_simulation(struct sdp_dev *dev, int report, unsigned char *...
function print_usage (line 375) | void print_usage(void)
function do_simulation_dev (line 400) | int do_simulation_dev(char const *base_path, char const *conf_path,
function do_autodetect_dev (line 447) | int do_autodetect_dev(char const *base_path, char const *conf_path,
type option (line 570) | struct option
function main (line 582) | int main(int argc, char * const argv[])
FILE: msvc/getopt.c
type ENUM_ORDERING (line 56) | enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }
type _getopt_data_a (line 64) | struct _getopt_data_a
function exchange_a (line 79) | static void exchange_a(char **argv, struct _getopt_data_a *d)
type _getopt_data_a (line 115) | struct _getopt_data_a
function _getopt_internal_r_a (line 136) | int _getopt_internal_r_a (int argc, char *const *argv, const char *optst...
function _getopt_internal_a (line 486) | int _getopt_internal_a (int argc, char *const *argv, const char *optstri...
function getopt_a (line 497) | int getopt_a (int argc, char *const *argv, const char *optstring) _GETOP...
function getopt_long_a (line 501) | int getopt_long_a (int argc, char *const *argv, const char *options, con...
function getopt_long_only_a (line 505) | int getopt_long_only_a (int argc, char *const *argv, const char *options...
function _getopt_long_r_a (line 509) | int _getopt_long_r_a (int argc, char *const *argv, const char *options, ...
function _getopt_long_only_r_a (line 513) | int _getopt_long_only_r_a (int argc, char *const *argv, const char *opti...
type _getopt_data_w (line 524) | struct _getopt_data_w
function exchange_w (line 539) | static void exchange_w(wchar_t **argv, struct _getopt_data_w *d)
function wchar_t (line 575) | static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, st...
function _getopt_internal_r_w (line 596) | int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t ...
function _getopt_internal_w (line 946) | int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *o...
function getopt_w (line 957) | int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) ...
function getopt_long_w (line 961) | int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *option...
function getopt_long_only_w (line 965) | int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *o...
function _getopt_long_r_w (line 969) | int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *opt...
function _getopt_long_only_r_w (line 973) | int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t...
FILE: msvc/getopt.h
type option_a (line 90) | struct option_a
function _GETOPT_API (line 98) | extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char ...
type option_w (line 112) | struct option_w
type option_w (line 113) | struct option_w
FILE: sdp.c
type sdp_command (line 11) | struct sdp_command {
function sdp_fill_read_reg (line 28) | static int sdp_fill_read_reg(unsigned char *buf, unsigned addr, unsigned...
function sdp_fill_write_reg (line 44) | static int sdp_fill_write_reg(unsigned char *buf, unsigned addr, unsigne...
function sdp_fill_status (line 60) | static int sdp_fill_status(unsigned char *buf)
function sdp_fill_dl_dcd (line 76) | static int sdp_fill_dl_dcd(unsigned char *buf, unsigned dcd_addr, int le...
function sdp_fill_write_file (line 92) | static int sdp_fill_write_file(unsigned char *buf, unsigned dladdr, unsi...
function sdp_fill_jump (line 108) | static int sdp_fill_jump(unsigned char *buf, unsigned header_addr)
function sdp_get_cmd_addr_cnt (line 124) | static int sdp_get_cmd_addr_cnt(unsigned char *buf,
type protocol_ops (line 157) | struct protocol_ops
function sdp_init_ops (line 167) | void sdp_init_ops(struct sdp_dev *dev)
FILE: sdp.h
type sdp_dev (line 1) | struct sdp_dev
FILE: sdps.c
type spds (line 14) | struct spds
function sdps_fill_read_reg (line 33) | static int sdps_fill_read_reg(unsigned char *buf, unsigned addr, unsigne...
function sdps_fill_write_reg (line 38) | static int sdps_fill_write_reg(unsigned char *buf, unsigned addr, unsign...
function sdps_fill_status (line 43) | static int sdps_fill_status(unsigned char *buf)
function sdps_fill_dl_dcd (line 48) | static int sdps_fill_dl_dcd(unsigned char *buf, unsigned dcd_addr, int l...
function sdps_fill_write_file (line 53) | static int sdps_fill_write_file(unsigned char *buf, unsigned dladdr, uns...
function sdps_fill_jump (line 69) | static int sdps_fill_jump(unsigned char *buf, unsigned header_addr)
type protocol_ops (line 74) | struct protocol_ops
function sdps_init_ops (line 83) | void sdps_init_ops(struct sdp_dev *dev)
FILE: sdps.h
type sdp_dev (line 2) | struct sdp_dev
Condensed preview — 47 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,088K chars).
[
{
"path": ".gitignore",
"chars": 78,
"preview": "*.o\nimx_usb\nimx_uart\nimx_usb.lds\nimx_uart.lds\n*.bin\n*.imx\n.*.swp\ntests/*.test\n"
},
{
"path": "COPYING",
"chars": 26530,
"preview": " GNU LESSER GENERAL PUBLIC LICENSE\n Version 2.1, February 1999\n\n Copyright (C) 19"
},
{
"path": "Makefile",
"chars": 1663,
"preview": "all: imx_usb imx_uart\n\nDESTDIR ?=\nprefix ?= /usr\nbindir ?= $(prefix)/bin\nsysconfdir ?= $(prefix)/etc\nrel_sysconfdir = $("
},
{
"path": "Makefile.mingw",
"chars": 881,
"preview": "all: imx_usb imx_uart\r\n\r\n#$(foreach v,$(.VARIABLES), $(info $(v) = $($(v))))\r\n\r\n# Building with MinGW natively\r\nCC = gcc"
},
{
"path": "README.md",
"chars": 2951,
"preview": "# imx_loader\n\ni.MX/Vybrid recovery utility\n\n## Description\nThis utility allows to download and execute code on Freescale"
},
{
"path": "image.h",
"chars": 7523,
"preview": "/*\n * (C) Copyright 2008 Semihalf\n *\n * (C) Copyright 2000-2005\n * Wolfgang Denk, DENX Software Engineering, wd@denx.de."
},
{
"path": "imx_loader.h",
"chars": 922,
"preview": "/*\n * imx_loader common header file for imx_usb/imx_uart\n *\n * This library is free software; you can redistribute it an"
},
{
"path": "imx_loader_config.c",
"chars": 11497,
"preview": "/*\n * imx_loader_config:\n * Configuration file parser for imx_usb/imx_uart loader\n *\n * This library is free software; y"
},
{
"path": "imx_loader_config.h",
"chars": 1350,
"preview": "/*\n * imx_loader_config:\n * Configuration file parser for imx_usb/imx_uart loader\n *\n * This library is free software; y"
},
{
"path": "imx_sdp.c",
"chars": 37555,
"preview": "/*\n * imx_sdp:\n * Implementation of the Serial Download Protocol (SDP) for i.MX/Vybrid\n * series processors.\n *\n * This "
},
{
"path": "imx_sdp.h",
"chars": 3658,
"preview": "/*\n * imx_sdp:\n * Interface of the Serial Download Protocol (SDP) for i.MX/Vybrid\n * series processors.\n *\n * This libra"
},
{
"path": "imx_sdp_simulation.c",
"chars": 3619,
"preview": "/*\n * imx_sdp_simulation:\n * A simple client side implementation of the Serial Download Protocol (SDP)\n * for testing.\n "
},
{
"path": "imx_sdp_simulation.h",
"chars": 1136,
"preview": "/*\n * imx_sdp_simulation:\n * A simple client side implementation of the Serial Download Protocol (SDP)\n * for testing.\n "
},
{
"path": "imx_uart.c",
"chars": 9764,
"preview": "/*\n * imx_uart:\n *\n * Program to download and execute an image over the serial boot protocol\n * on i.MX series processor"
},
{
"path": "imx_usb.c",
"chars": 16394,
"preview": "/*\n * imx_usb:\n *\n * Program to download and execute an image over the USB boot protocol\n * on i.MX series processors.\n "
},
{
"path": "imx_usb.conf",
"chars": 778,
"preview": "#vid:pid, config_file\n0x066f:0x3780, mx23_usb_work.conf\n0x15a2:0x004f, mx28_usb_work.conf\n0x15a2:0x0052, mx50_usb_work.c"
},
{
"path": "msvc/getopt.c",
"chars": 26452,
"preview": "/* Getopt for Microsoft C\nThis code is a modification of the Free Software Foundation, Inc.\nGetopt library for parsing c"
},
{
"path": "msvc/getopt.h",
"chars": 4878,
"preview": "/* Getopt for Microsoft C\nThis code is a modification of the Free Software Foundation, Inc.\nGetopt library for parsing c"
},
{
"path": "msvc/imx_loader.sln",
"chars": 1775,
"preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 14\r\nVisualStudioVersion = 14.0.25420.1\r\n"
},
{
"path": "msvc/imx_uart.vcxproj",
"chars": 5437,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micro"
},
{
"path": "msvc/imx_usb.vcxproj",
"chars": 6380,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micro"
},
{
"path": "mx50_usb_work.conf",
"chars": 710,
"preview": "mx50\n#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)\nhid,64,0xf8006400,0xf"
},
{
"path": "mx51_usb_work.conf",
"chars": 895,
"preview": "mx51\n#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)\nbulk,old_header,64,0x"
},
{
"path": "mx53_usb_work.conf",
"chars": 865,
"preview": "mx53\n#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)\nbulk,512,0xf8006000,0"
},
{
"path": "mx6_usb_sdp_spl.conf",
"chars": 220,
"preview": "mx6_spl_sdp\n#hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat valid ram areas)\n#In SPL, we typically "
},
{
"path": "mx6_usb_work.conf",
"chars": 1487,
"preview": "mx6_qsb\n#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)\nhid,1024,0x91000"
},
{
"path": "mx6ull_usb_work.conf",
"chars": 284,
"preview": "mx6ull\n#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)\nhid,1024,0x910000"
},
{
"path": "mx7_usb_work.conf",
"chars": 1270,
"preview": "mx7\n#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)\nhid,1024,0x910000,0x80"
},
{
"path": "mx7ulp_usb_work.conf",
"chars": 152,
"preview": "mx7ulp\n#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)\nhid,1024,0x2f020000"
},
{
"path": "mx8m_usb_sdp_spl.conf",
"chars": 647,
"preview": "mx8m_spl_sdp\n#hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat valid ram areas)\n#In SPL, we typically"
},
{
"path": "mx8mm_usb_work.conf",
"chars": 227,
"preview": "mx8mm_qsb\n#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)\nhid,1024,0x910"
},
{
"path": "mx8mn_usb_work.conf",
"chars": 244,
"preview": "mx8mn\n#hid/bulk/sdps,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)\nsdps,no-hid-c"
},
{
"path": "mx8mq_usb_work.conf",
"chars": 385,
"preview": "mx8_qsb\n#hid/bulk,[old_header,]max packet size, dcd_addr, {ram start, ram size}(repeat valid ram areas)\nhid,1024,0x91000"
},
{
"path": "portable.h",
"chars": 1884,
"preview": "#ifndef __PORTABLE_H__\n#define __PORTABLE_H__\n\nextern int debugmode;\n\n#ifndef WIN32\n#define dbg_printf(fmt, args...)\tdo{"
},
{
"path": "sdp.c",
"chars": 3549,
"preview": "#include <stdio.h>\n#include <sys/types.h>\n#include <time.h>\n#include <ctype.h>\n#include <errno.h>\n#include <string.h>\n#i"
},
{
"path": "sdp.h",
"chars": 40,
"preview": "void sdp_init_ops(struct sdp_dev *dev);\n"
},
{
"path": "sdps.c",
"chars": 2079,
"preview": "#include <stdio.h>\n#include <sys/types.h>\n#include <time.h>\n\n#include <ctype.h>\n#include <errno.h>\n#include <string.h>\n\n"
},
{
"path": "sdps.h",
"chars": 42,
"preview": "\nvoid sdps_init_ops(struct sdp_dev *dev);\n"
},
{
"path": "tests/Makefile",
"chars": 339,
"preview": "IMX_USB ?= ../imx_usb\n\n%.test: % FORCE\n\t@echo Testing $*\n\t@$(IMX_USB) -v -S 0x15a2:0x0061 $* > $@\n\t@diff -u $*.output $@"
},
{
"path": "tests/bare.cfg",
"chars": 29,
"preview": "IMAGE_VERSION 2\nBOOT_FROM sd\n"
},
{
"path": "tests/create.txt",
"chars": 298,
"preview": "=> IMX image with plugin\nmkimage -n plugin.cfg -T imximage -a -e 0x87800000 -d image.bin test-plugin.imx\n=> IMX image wi"
},
{
"path": "tests/dcd.cfg",
"chars": 59,
"preview": "IMAGE_VERSION 2\nBOOT_FROM sd\n\nDATA 4 0x30000000 0x12345678\n"
},
{
"path": "tests/plugin.cfg",
"chars": 58,
"preview": "IMAGE_VERSION 2\nBOOT_FROM sd\nPLUGIN plugin.bin 0x00907000\n"
},
{
"path": "tests/test-dcd.imx.output",
"chars": 43464,
"preview": "config file <..//imx_usb.conf>\nvid=0x066f pid=0x3780 file_name=mx23_usb_work.conf\nvid=0x15a2 pid=0x004f file_name=mx28_u"
},
{
"path": "tests/test-plugin.imx.output",
"chars": 773471,
"preview": "config file <..//imx_usb.conf>\nvid=0x066f pid=0x3780 file_name=mx23_usb_work.conf\nvid=0x15a2 pid=0x004f file_name=mx28_u"
},
{
"path": "tests/test.imx.output",
"chars": 43145,
"preview": "config file <..//imx_usb.conf>\nvid=0x066f pid=0x3780 file_name=mx23_usb_work.conf\nvid=0x15a2 pid=0x004f file_name=mx28_u"
},
{
"path": "vybrid_usb_work.conf",
"chars": 786,
"preview": "vybrid\n#hid/bulk,[old_header,]max packet size,dcd_addr,{ram start, ram size}(repeat valid ram areas)\n#SysRAM0\n#hid,1024,"
}
]
About this extraction
This page contains the full source code of the boundarydevices/imx_usb_loader GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 47 files (1023.3 KB), approximately 596.5k tokens, and a symbol index with 153 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.