initial commit
This commit is contained in:
commit
d7e870010d
97 changed files with 15413 additions and 0 deletions
18
CMakeLists.txt
Normal file
18
CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
cmake_minimum_required(VERSION 2.8.4)
|
||||
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_SOURCE_DIR}/cmake
|
||||
${CMAKE_MODULE_PATH})
|
||||
|
||||
project(Heimdall)
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
option(DISABLE_FRONTEND "Disable GUI frontend" OFF)
|
||||
|
||||
add_subdirectory(libpit)
|
||||
add_subdirectory(heimdall)
|
||||
if(NOT DISABLE_FRONTEND)
|
||||
add_subdirectory(heimdall-frontend)
|
||||
add_dependencies(heimdall-frontend heimdall)
|
||||
endif()
|
19
LICENSE
Normal file
19
LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
492
Linux/README
Normal file
492
Linux/README
Normal file
|
@ -0,0 +1,492 @@
|
|||
Heimdall (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
http://www.glassechidna.com.au/products/heimdall/
|
||||
|
||||
DISCLAIMER:
|
||||
|
||||
This software attempts to flash your Galaxy S device. The very nature of
|
||||
flashing is dangerous. As with all flashing software, Heimdall has the
|
||||
potential to damage (brick) your device if not used carefully. If you're
|
||||
concerned, don't use this software. Flashing ROMs onto your phone may also
|
||||
void your warranty. Benjamin Dobell and Glass Echidna are not responsible
|
||||
for the result of your actions.
|
||||
|
||||
|
||||
These instructions are for Linux operating systems.
|
||||
|
||||
|
||||
Flashing Heimdall Firmware Package with Heimdall Frontend:
|
||||
|
||||
As of Heimdall Frontend 1.3 there are now two main ways to flash a ROM from
|
||||
Heimdall Frontend. The simpler and preferred option is to download a
|
||||
Heimdall Firmware Package and follow the following steps.
|
||||
|
||||
|
||||
1. Fully charge your device (use the wall charger as it's faster).
|
||||
|
||||
2. Open the a terminal and run Heimdall Frontend by typing:
|
||||
|
||||
heimdall-frontend
|
||||
|
||||
3. From the "Load Package" tab, under the "Heimdall Firmware Package"
|
||||
section click the "Browse" button.
|
||||
|
||||
4. Use the dialogue that appears to navigate to, and select, the Heimdall
|
||||
firmware package that you wish to flash.
|
||||
|
||||
5. You will see progress bars appear as the package is decompressed and
|
||||
extracted.
|
||||
|
||||
When the package has finished being decompressed you should see
|
||||
information about the particular firmware package that has been
|
||||
selected.
|
||||
|
||||
6. Verify that your device is listed under "Supported Devices". If it's not
|
||||
then STOP immediately! DO NOT flash this firmware to your device!
|
||||
Instead search for an appropriate firmware package for your device.
|
||||
|
||||
If you believe there is a mistake and your device is actually
|
||||
supported please get in contact with the firmware developer (not Glass
|
||||
Echidna!) and ask them to rectify the issue. If the developer provided
|
||||
a URL you may be able to contact them by pressing the "Homepage" button.
|
||||
|
||||
7. If you've verified your device is supported you may continue to press
|
||||
the "Load / Customise" button.
|
||||
|
||||
8. You should now be looking at the "Flash" tab. If not verify that you did
|
||||
in fact push the "Load / Customise" button.
|
||||
|
||||
Generally, you won't NEED or WANT to customise a firmware package! In
|
||||
which case you can safely move on to step 9.
|
||||
|
||||
Nonetheless, the "Flash" tab provides you with a means to customise the
|
||||
firmware package before flashing it to your device. See "Performing a
|
||||
Custom Flash with Heimdall Frontend" for more details.
|
||||
|
||||
9. Put your Galaxy S device into download mode and plug it in to your PC.
|
||||
|
||||
Download mode can be accessed several different ways depending on your
|
||||
particular device model. If you're unsure how to do this please search
|
||||
online for the appropriate method.
|
||||
|
||||
10. Press the "Start" button.
|
||||
|
||||
11. Heimdall Frontend will display the progress and inform you when the
|
||||
flash is complete.
|
||||
|
||||
If something went wrong i.e. your device wasn't detected because it
|
||||
wasn't in download mode, then the status section will let you know the
|
||||
cause of the problem.
|
||||
|
||||
|
||||
|
||||
Performing a Custom Flash with Heimdall Frontend:
|
||||
|
||||
This is the advanced means of flashing firmware to your device.
|
||||
|
||||
If you're not an advanced user or a developer, in the event that a Heimdall
|
||||
Firmware Package doesn't exist for the particular firmware (or files) that
|
||||
you wish to flash, then I strongly recommend you get in touch with the
|
||||
developer of the firmware (or files) and politely ask them to create a
|
||||
Heimdall Firmware Package for you. In doing so, you avoid the risk of
|
||||
making mistakes due to inexperience.
|
||||
|
||||
|
||||
If you're looking to customise an existing Heimdall Firmware Package then
|
||||
follow steps 1-8 of "Flashing Heimdall Firmware Package with Heimdall
|
||||
Frontend" then start from below with step 5.
|
||||
|
||||
|
||||
1. Fully charge your device (use the wall charger as it's faster).
|
||||
|
||||
2. Download a decrypted device ROM or a Heimdall Firmware Package
|
||||
and extract everything to the one directory.
|
||||
|
||||
3. If the ROM is not a Heimdall Firmware Package it may instead be provided
|
||||
as multiple archives (nested or otherwise), extract them all to the same
|
||||
location.
|
||||
|
||||
NOTE: If you want to use the CSC then extract it last. If you're asked
|
||||
to overwrite files then do so.
|
||||
|
||||
3. Open the a terminal and run Heimdall Frontend by typing:
|
||||
|
||||
heimdall-frontend
|
||||
|
||||
4. Select the "Flash" tab. From the "Flash" tab you're able to completely
|
||||
customise a flash.
|
||||
|
||||
5. Before you can chose which partitions you want to flash with particular
|
||||
files you MUST first select a PIT file. To do this click the "Browse"
|
||||
button in the "PIT" section. This will open a dialogue allowing you to
|
||||
navigate to and select a valid PIT (.pit) file.
|
||||
|
||||
If you do not already have a valid PIT file stored on your computer you
|
||||
can download your device's PIT file from the "Utilities" tab.
|
||||
|
||||
6. If a valid PIT file has been selected then the "Add" button below the
|
||||
"Partitions (Files)" list-box will be enabled. Press this button to add
|
||||
a partition to your flash.
|
||||
|
||||
7. When you first add a partition you will see the "Partition Name" and
|
||||
"Partition ID" be populated with information. Use the "Partition Name"
|
||||
drop down to select which partition you wish to flash. "Partition ID"
|
||||
will automatically update and is never directly editable.
|
||||
|
||||
8. You must then select a file to flash to the partition that you just
|
||||
specified using the "Browse" button under the "File / Partition". You
|
||||
will not be able to flash, create a firmware package or add another
|
||||
partition until you have selected a file. However, you're still able to
|
||||
press the "Remove" button if you've decided not to flash the partition
|
||||
you've just specified.
|
||||
|
||||
9. When you've specified a file name then you'll be able to see the updated
|
||||
information in the partition list to the right. You can select any
|
||||
partition from this list and customise it as you see fit.
|
||||
|
||||
You can also remove a partition from the list by selecting it and
|
||||
clicking the "Remove" button. Removing a partition from the list doesn't
|
||||
remove it from your device, it simply means it will not be flashed.
|
||||
|
||||
10. Repeat steps 7-9 as often as needed to specify all the partitions/files
|
||||
that you wish to flash.
|
||||
|
||||
11. Now you can chose whether you would like to repartition your device as
|
||||
well as whether you would like to prevent the device rebooting once a
|
||||
flash has been completed. These options can be enabled or disabled by
|
||||
toggling the "Repartition" and "No Reboot" check-boxes.
|
||||
|
||||
In the general case you will only need to enable repartition if you wish
|
||||
to change the PIT file on your device. Keep in mind that repartitioning
|
||||
will wipe your device!
|
||||
|
||||
The "No Reboot" option is rarely required. It's mostly in place so you
|
||||
can manually boot straight into recovery mode after a flash (rather than
|
||||
booting up normally).
|
||||
|
||||
12. If you've added at least one partition to your flash (and selected a
|
||||
file for that partition) then the "Start" button will be enabled. Press
|
||||
the "Start" button to begin the flashing process.
|
||||
|
||||
You may notice that the "Create Package" tab becomes available at the
|
||||
whenever the "Start" button becomes available. From this tab you're able
|
||||
to create a reusable, redistributable Heimdall Firmware Package with the
|
||||
files and partitions you just selected. See "How to Create a Heimdall
|
||||
Firmware Package" for details.
|
||||
|
||||
13. Heimdall Frontend will display the progress and inform you when the
|
||||
flash is complete.
|
||||
|
||||
If something went wrong i.e. your device wasn't detected because it
|
||||
wasn't in download mode, then the status section will let you know the
|
||||
cause of the problem.
|
||||
|
||||
|
||||
|
||||
Flashing Firmware from Command Line:
|
||||
|
||||
1. Fully charge your phone (use the wall charger as it's faster).
|
||||
|
||||
2. Download a decrypted device ROM or a Heimdall Firmware Package
|
||||
and extract everything to the one directory.
|
||||
|
||||
3. If the ROM is not a Heimdall Firmware Package it may instead be provided
|
||||
as multiple archives (nested or otherwise), extract them all to the same
|
||||
location.
|
||||
|
||||
NOTE: If you want to use the CSC then extract it last.
|
||||
|
||||
4. Put your Galaxy S device into download mode and plug it in..
|
||||
|
||||
5. Open a terminal and navigate to the directory where you extracted
|
||||
the ROM/firmware files.
|
||||
|
||||
6. Type the following to list all the functionality Heimdall supports:
|
||||
|
||||
heimdall help
|
||||
|
||||
7. Before flashing, you must first know the names of the partitions you
|
||||
wish to flash. These can be obtained by executing:
|
||||
|
||||
heimdall print-pit --no-reboot
|
||||
|
||||
The inclusion of --no-reboot ensures the phone will not reboot after PIT
|
||||
file has been downloaded and displayed. After executing a command with
|
||||
the --no-reboot argument, the next command should include the --resume
|
||||
argument.
|
||||
|
||||
NOTE: You can still safely reboot your phone manually (with the power
|
||||
button) after executing --no-reboot commands.
|
||||
|
||||
8. Use the help and print-pit output to construct a command with all the
|
||||
files you want to flash.
|
||||
|
||||
Here is an example that does a full flash and repartition on a GT-I9000:
|
||||
|
||||
heimdall flash --repartition --resume --pit s1_odin_20100512.pit --FACTORYFS factoryfs.rfs --CACHE cache.rfs --DBDATA dbdata.rfs --IBL+PBL boot.bin --SBL Sbl.bin --PARAM param.lfs --KERNEL zImage --MODEM modem.bin
|
||||
|
||||
9. Heimdall will display the progress as it flashes so that you know things
|
||||
are working as they should.
|
||||
|
||||
|
||||
|
||||
How to Create a Heimdall Firmware Package:
|
||||
|
||||
Firstly, Heimdall's firmware package format is just a regular TAR archive
|
||||
compressed with gzip. The only two real requirements are that a valid
|
||||
firmware.xml must be included (refer to Appendix A) and you can only
|
||||
include files (no directories, links etc.) As such if you'd like there is
|
||||
nothing preventing you from creating Heimdall packages manually. Of course
|
||||
Heimdall Frontend provides a simple user interface that takes care of all
|
||||
the hard work for you.
|
||||
|
||||
There are two ways in which you can create a firmware package. You can
|
||||
create a package from scratch, or you can load an existing package, apply
|
||||
modifications and then save the package. Creating a package from scratch
|
||||
is the preferred approach, by taking this approach you're far less likely
|
||||
to run into file name length limitations.
|
||||
|
||||
Before you can access Heimdall Frontend's firmware creation functionality
|
||||
(available from the "Create Package" tab) you must first specify which
|
||||
files will be included in your package, as well as a few flashing options
|
||||
i.e. Whether or not users should repartition when flashing. This
|
||||
information must be filled out from the "Flash" tab in exactly the same
|
||||
fashion you would provide information to flash your device (see "Performing
|
||||
a Custom Flash with Heimdall Frontend"). As mentioned above, it's not the
|
||||
preferred means, but you're able to load an existing package as a starting
|
||||
point for this information.
|
||||
|
||||
Once you've specified the files/partitions you wish to include in your
|
||||
firmware package the "Create Package" tab will become available. Clicking
|
||||
this tab will display additional information that you can include in your
|
||||
package. In order to continue you must fill out all sections except for the
|
||||
URLs section, which is optional. The following is a break-down of what all
|
||||
these options mean.
|
||||
|
||||
- General Firmware Information: -
|
||||
|
||||
Firmware Name - This is the name of your particular firmware. An
|
||||
example would be "Cyanogenmod".
|
||||
|
||||
Firmware Version - This is the version identifier for your package. Any
|
||||
valid string will be accepted, although the inclusion of decimal
|
||||
point version number is preferred i.e. "7.1". If it makes sense
|
||||
then feel free to append a text string like "RC1" or "Beta 1" to
|
||||
the decimal point version.
|
||||
|
||||
Platform Name - This is the name of platform (or operating system) that
|
||||
your firmware is based on. In most cases this will simply be
|
||||
"Android".
|
||||
|
||||
Platform Version - This is the operating system version that your
|
||||
firmware is based on. Again decimal point version numbers are
|
||||
preferred over text, i.e. "2.3.4" is preferred over "Gingerbread".
|
||||
|
||||
|
||||
- Developers -
|
||||
|
||||
URLs (Optional):
|
||||
|
||||
Homepage - Here you can enter your personal URL or a URL particularly
|
||||
pertaining to the firmware being packaged. The URL must be well
|
||||
formed for it to work. An example of a well formed URL is
|
||||
"http://www.glassechidna.com.au/products/heimdall/". It is
|
||||
important to include "http://" in order to specify the protocol as
|
||||
other protocols such as "ftp://" are equally valid although
|
||||
unlikely to be used.
|
||||
|
||||
Donate - Here you can enter a URL that will link users to a page to
|
||||
make donations for the effort you've put into developing your
|
||||
firmware. Once again the URL must be well formed but there is no
|
||||
requirement on how your donation page should work. For instance
|
||||
both "http://www.glassechidna.com.au/donate/" and
|
||||
"http://forum.xda-developers.com/donatetome.php?u=2710388" are
|
||||
equally valid.
|
||||
|
||||
Developer Info:
|
||||
|
||||
Name - Here you can enter in the name of individual team members or a
|
||||
team name. Click "Add" and the developer will be added to the list
|
||||
on the right. If you make a mistake you can select a developer from
|
||||
the list and click "Remove". You can list as many developers as you
|
||||
like, however visual constraints of the "Load Package" tab means
|
||||
only a few names will be visible. Where possible you may want to
|
||||
opt for team names over listing individual team members.
|
||||
|
||||
|
||||
- Supported Devices -
|
||||
|
||||
This section allows you to create a list of devices that are supported by
|
||||
your particular firmware. Although Heimdall isn't capable of enforcing this
|
||||
we strongly recommend you take this section seriously. If filled out
|
||||
correctly you could help save a number of accidental bricks!
|
||||
|
||||
Device Info:
|
||||
|
||||
Manufacturer - This is where you can enter the name of the manufacturer
|
||||
for a particular device. For now this will most likely be
|
||||
"Samsung".
|
||||
|
||||
Name - This is the human readable name for a particular device.
|
||||
"Galaxy S", "Galaxy S II", "Droid Charge", "Vibrant" and
|
||||
"Galaxy S (Telstra)" are all valid names. There are a lot of
|
||||
possible variations here so be as specific as you think is
|
||||
necessary.
|
||||
|
||||
Product Code - This is by far the most important bit of device
|
||||
information. Device names tend to be region specific and further
|
||||
subject to the whims of telecommunication companies and resellers.
|
||||
Product Codes (or product IDs) are designated by manufacturers and
|
||||
are generally the definitive means of referring to a particular
|
||||
device. Examples are "GT-I9000", "GT-I9100" and "SCH-I897". If
|
||||
you're unsure of a particular product code then both Google and
|
||||
GSMArena are your friends!
|
||||
|
||||
|
||||
After filling out all the necessary information the "Build" button will be
|
||||
enabled. If it's still disabled then you know you're missing some required
|
||||
information. In particular you must specify at least one developer and at
|
||||
least one supported device. Pressing the "Build" button will bring up a
|
||||
save dialogue where you must chose a file name for your particular package.
|
||||
Don't worry about specifying the ".tar.gz" extension Heimdall Frontend will
|
||||
take care of this automatically.
|
||||
|
||||
Once you've chosen a file name Heimdall Frontend will begin the process of
|
||||
building the firmware package. In doing so a valid firmware.xml file will
|
||||
be generated from the information entered. All files will be archived in a
|
||||
single TAR file then the TAR archive will be compressed via gzip
|
||||
compression. Compression will take a little while but you will see progress
|
||||
bars so you know the application hasn't hung. When the progress bars
|
||||
disappear you're finished making your package.
|
||||
|
||||
Congratulations! You're now ready to redistribute your firmware package
|
||||
online or by any means you see fit.
|
||||
|
||||
|
||||
|
||||
Appendix A - firmware.xml
|
||||
|
||||
The following details a part of the Heimdall Firmware Package format. This
|
||||
is only relevant to developers or advanced users who wish to create Heimdall
|
||||
Firmware Packages outside of Heimdall Frontend or in some way integrate support
|
||||
for the format in their own software.
|
||||
|
||||
|
||||
All Heimdall Firmware Packages must contain a file called firmware.xml. This
|
||||
file stores flash information and meta-data for the package as well as
|
||||
information about other files contained within the package.
|
||||
|
||||
|
||||
The format is fairly straight-forward so it won't be explained in great detail.
|
||||
Nonetheless the following is an example of a valid firmware.xml file.
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<firmware version="1">
|
||||
<name>Test Firmware</name>
|
||||
<version>1.1</version>
|
||||
<platform>
|
||||
<name>Android</name>
|
||||
<version>2.3.4</version>
|
||||
</platform>
|
||||
<developers>
|
||||
<name>Benjamin Dobell</name>
|
||||
<name>Hedonism Bot</name>
|
||||
</developers>
|
||||
<url>http://www.glassechidna.com.au/</url>
|
||||
<donateurl>http://www.glassechidna.com.au/donate/</donateurl>
|
||||
<devices>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000</product>
|
||||
<name>Galaxy S</name>
|
||||
</device>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000T</product>
|
||||
<name>Galaxy S (Telstra)</name>
|
||||
</device>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000M</product>
|
||||
<name>Vibrant</name>
|
||||
</device>
|
||||
</devices>
|
||||
<pit>Nl3276-I9000 s1_odin_20100512.pit</pit>
|
||||
<repartition>0</repartition>
|
||||
<noreboot>0</noreboot>
|
||||
<files>
|
||||
<file>
|
||||
<id>0</id>
|
||||
<filename>gq3276-boot.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>24</id>
|
||||
<filename>Uh3276-cache.rfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>22</id>
|
||||
<filename>em3276-factoryfs.rfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>11</id>
|
||||
<filename>fl3276-modem.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>21</id>
|
||||
<filename>Xd3276-param.lfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>3</id>
|
||||
<filename>if3276-Sbl.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>6</id>
|
||||
<filename>cr3276-zImage</filename>
|
||||
</file>
|
||||
</files>
|
||||
</firmware>
|
||||
|
||||
|
||||
New lines need not be included and the order in which elements are specified
|
||||
does not need to match that of the above example.
|
||||
|
||||
One and only one <firmware> element must be included. The <firmware> element
|
||||
must also have a version attribute specified. The version must be parsable as
|
||||
an integer and indicates what version of the Heimdall Firmware Package
|
||||
specification the package adheres to.
|
||||
|
||||
All data is stored as strings, however a <file>'s <id> element must be parsable
|
||||
as an integer. The <id> value represents the partition ID (according to the
|
||||
specified PIT file) that the file should be flashed to.
|
||||
|
||||
A <firmware>'s <repartition> and <noreboot> elements must also be parsable as
|
||||
an integer. However, as they represent boolean values, a value of zero ("0")
|
||||
means false (or disabled) where as a non-zero value (typically "1") means true
|
||||
(or enabled).
|
||||
|
||||
File names are specified relative to the TAR archive in which firmware.xml and
|
||||
all other files are to be stored. Heimdall Firmware Packages do not support
|
||||
directories or links, as such file names should only be a name and not a path.
|
||||
|
||||
<url> and <donateurl> are the only optional elements, all other elements must
|
||||
be included.
|
||||
|
||||
|
||||
|
||||
Appendix B - Installing Heimdall Suite from Source:
|
||||
|
||||
1. First make sure you have installed build-essential, cmake, zlib1g-dev,
|
||||
qt5-default, libusb-1.0-0-dev and OpenGL (e.g libgl1-mesa-glx and
|
||||
libgl1-mesa-dev).
|
||||
|
||||
NOTE: Package names may not be absolutely identical to those above.
|
||||
|
||||
2. Open a terminal and navigate to the directory you downloaded,
|
||||
or extracted, Heimdall to.
|
||||
|
||||
3. Enter the following commands to compile Heimdall Suite:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make
|
||||
|
491
OSX/README.txt
Normal file
491
OSX/README.txt
Normal file
|
@ -0,0 +1,491 @@
|
|||
Heimdall (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
http://www.glassechidna.com.au/products/heimdall/
|
||||
|
||||
DISCLAIMER:
|
||||
|
||||
This software attempts to flash your Galaxy S device. The very nature of
|
||||
flashing is dangerous. As with all flashing software, Heimdall has the
|
||||
potential to damage (brick) your device if not used carefully. If you're
|
||||
concerned, don't use this software. Flashing ROMs onto your phone may also
|
||||
void your warranty. Benjamin Dobell and Glass Echidna are not responsible
|
||||
for the result of your actions.
|
||||
|
||||
|
||||
These instructions are for OS X operating systems.
|
||||
|
||||
|
||||
Installing Heimdall and Heimdall Frontend Binaries:
|
||||
|
||||
1. Run "Heimdall Suite.pkg" and follow the instructions.
|
||||
|
||||
2. Reboot your system.
|
||||
|
||||
3. Done
|
||||
|
||||
|
||||
|
||||
Flashing Heimdall Firmware Package with Heimdall Frontend:
|
||||
|
||||
As of Heimdall Frontend 1.3 there are now two main ways to flash a ROM from
|
||||
Heimdall Frontend. The simpler and preferred option is to download a
|
||||
Heimdall Firmware Package and follow the following steps.
|
||||
|
||||
|
||||
1. Fully charge your device (use the wall charger as it's faster).
|
||||
|
||||
2. Open the Heimdall Frontend (heimdall-frontend) application.
|
||||
|
||||
3. From the "Load Package" tab, under the "Heimdall Firmware Package"
|
||||
section click the "Browse" button.
|
||||
|
||||
4. Use the dialogue that appears to navigate to, and select, the Heimdall
|
||||
firmware package that you wish to flash.
|
||||
|
||||
5. You will see progress bars appear as the package is decompressed and
|
||||
extracted.
|
||||
|
||||
When the package has finished being decompressed you should see
|
||||
information about the particular firmware package that has been
|
||||
selected.
|
||||
|
||||
6. Verify that your device is listed under "Supported Devices". If it's not
|
||||
then STOP immediately! DO NOT flash this firmware to your device!
|
||||
Instead search for an appropriate firmware package for your device.
|
||||
|
||||
If you believe there is a mistake and your device is actually
|
||||
supported please get in contact with the firmware developer (not Glass
|
||||
Echidna!) and ask them to rectify the issue. If the developer provided
|
||||
a URL you may be able to contact them by pressing the "Homepage" button.
|
||||
|
||||
7. If you've verified your device is supported you may continue to press
|
||||
the "Load / Customise" button.
|
||||
|
||||
8. You should now be looking at the "Flash" tab. If not verify that you did
|
||||
in fact push the "Load / Customise" button.
|
||||
|
||||
Generally, you won't NEED or WANT to customise a firmware package! In
|
||||
which case you can safely move on to step 9.
|
||||
|
||||
Nonetheless, the "Flash" tab provides you with a means to customise the
|
||||
firmware package before flashing it to your device. See "Performing a
|
||||
Custom Flash with Heimdall Frontend" for more details.
|
||||
|
||||
9. Put your Galaxy S device into download mode and plug it in to your PC.
|
||||
|
||||
Download mode can be accessed several different ways depending on your
|
||||
particular device model. If you're unsure how to do this please search
|
||||
online for the appropriate method.
|
||||
|
||||
10. Press the "Start" button.
|
||||
|
||||
11. Heimdall Frontend will display the progress and inform you when the
|
||||
flash is complete.
|
||||
|
||||
If something went wrong i.e. your device wasn't detected because it
|
||||
wasn't in download mode, then the status section will let you know the
|
||||
cause of the problem.
|
||||
|
||||
|
||||
|
||||
Performing a Custom Flash with Heimdall Frontend:
|
||||
|
||||
This is the advanced means of flashing firmware to your device.
|
||||
|
||||
If you're not an advanced user or a developer, in the event that a Heimdall
|
||||
Firmware Package doesn't exist for the particular firmware (or files) that
|
||||
you wish to flash, then I strongly recommend you get in touch with developer
|
||||
of the firmware (or files) and politely ask them to create a Heimdall
|
||||
Firmware Package for you. In doing so then you don't have to worry about
|
||||
making mistakes due to inexperience.
|
||||
|
||||
If you're looking to customise an existing Heimdall Firmware Package then
|
||||
follow steps 1-8 of "Flashing Heimdall Firmware Package with Heimdall
|
||||
Frontend" then start from below with step 5.
|
||||
|
||||
|
||||
1. Fully charge your device (use the wall charger as it's faster).
|
||||
|
||||
2. Download a decrypted device ROM or a Heimdall Firmware Package
|
||||
and extract everything to the one directory.
|
||||
|
||||
3. If the ROM is not a Heimdall Firmware Package it may instead be provided
|
||||
as multiple archives (nested or otherwise), extract them all to the same
|
||||
location.
|
||||
|
||||
NOTE: If you want to use the CSC then extract it last.
|
||||
|
||||
3. Open the Heimdall Frontend (heimdall-frontend) application.
|
||||
|
||||
4. Select the "Flash" tab. From the "Flash" tab you're able to completely
|
||||
customise a flash.
|
||||
|
||||
5. Before you can chose which partitions you want to flash with particular
|
||||
files you MUST first select a PIT file. To do this click the "Browse"
|
||||
button in the "PIT" section. This will open a dialogue allowing you to
|
||||
navigate to and select a valid PIT (.pit) file.
|
||||
|
||||
If you do not already have a valid PIT file stored on your computer you
|
||||
can download your device's PIT file from the "Utilities" tab.
|
||||
|
||||
6. If a valid PIT file has been selected then "Add" button below the
|
||||
"Partitions (Files)" list-box will become enabled. Press this button to
|
||||
add a partition to your flash.
|
||||
|
||||
7. When you first add a partition you will see the "Partition Name" and
|
||||
"Partition ID" be populated with information. Use the "Partition Name"
|
||||
drop down to select which partition you wish to flash. "Partition ID"
|
||||
will automatically update and is never directly editable.
|
||||
|
||||
8. You must then select a file to flash to the partition that you just
|
||||
specified using the "Browse" button under the "File / Partition". You
|
||||
will not be able to flash, create a firmware package or add another
|
||||
partition until you have selected a file. However, you're still able to
|
||||
press the "Remove" button if you've decided not to flash the partition
|
||||
you've just specified.
|
||||
|
||||
9. When you've specified a file name then you'll be able to see the updated
|
||||
information in the partition list to the right. You can select any
|
||||
partition from this list and customise it as you see fit.
|
||||
|
||||
You can also remove a partition from the list by selecting it and
|
||||
clicking the "Remove" button. Removing a partition from the list doesn't
|
||||
remove it from your device, it simply means it will not be flashed.
|
||||
|
||||
10. Repeat steps 7-9 as often as needed to specify all the partitions/files
|
||||
that you wish to flash.
|
||||
|
||||
11. Now you can chose whether you would like to repartition your device as
|
||||
well as whether you would like to prevent the device rebooting once a
|
||||
flash has been completed. These options can be enabled or disabled by
|
||||
toggling the "Repartition" and "No Reboot" check-boxes.
|
||||
|
||||
In the general case you will only need to enable repartition if you wish
|
||||
to change the PIT file on your device. Keep in mind that repartitioning
|
||||
will wipe your device!
|
||||
|
||||
The "No Reboot" option is rarely required. It's mostly in place so you
|
||||
can manually boot straight into recovery mode after a flash (rather than
|
||||
booting up normally).
|
||||
|
||||
12. If you've added at least one partition to your flash (and selected a
|
||||
file for that partition) then the "Start" button will be enabled. Press
|
||||
the "Start" button to begin the flashing process.
|
||||
|
||||
You may notice that the "Create Package" tab becomes available at the
|
||||
whenever the "Start" button becomes available. From this tab you're able
|
||||
to create a reusable, redistributable Heimdall Firmware Package with the
|
||||
files and partitions you just selected. See "How to Create a Heimdall
|
||||
Firmware Package" for details.
|
||||
|
||||
13. Heimdall Frontend will display the progress and inform you when the
|
||||
flash is complete.
|
||||
|
||||
If something went wrong i.e. your device wasn't detected because it
|
||||
wasn't in download mode, then the status section will let you know the
|
||||
cause of the problem.
|
||||
|
||||
|
||||
|
||||
Flashing Firmware from Command Line:
|
||||
|
||||
1. Fully charge your phone (use the wall charger as it's faster).
|
||||
|
||||
2. Download a decrypted device ROM or a Heimdall Firmware Package
|
||||
and extract everything to the one directory.
|
||||
|
||||
3. If the ROM is not a Heimdall Firmware Package it may instead be provided
|
||||
as multiple archives (nested or otherwise), extract them all to the same
|
||||
location.
|
||||
|
||||
NOTE: If you want to use the CSC then extract it last. If you're asked
|
||||
to overwrite files then do so.
|
||||
|
||||
4. Put your Galaxy S device into download mode and plug it in..
|
||||
|
||||
5. Open a terminal and navigate to the directory where you extracted
|
||||
the ROM/firmware files.
|
||||
|
||||
6. Type the following to list all the functionality Heimdall supports:
|
||||
|
||||
heimdall help
|
||||
|
||||
7. Before flashing, you must first know the names of the partitions you
|
||||
wish to flash. These can be obtained by executing:
|
||||
|
||||
heimdall print-pit --no-reboot
|
||||
|
||||
The inclusion of --no-reboot ensures the phone will not reboot after PIT
|
||||
file has been downloaded and displayed. After executing a command with
|
||||
the --no-reboot argument, the next command should include the --resume
|
||||
argument.
|
||||
|
||||
NOTE: You can still safely reboot your phone manually (with the power
|
||||
button) after executing --no-reboot commands.
|
||||
|
||||
8. Use the help and print-pit output to construct a command with all the
|
||||
file you want to flash.
|
||||
|
||||
Here is an example that does a full flash and repartition on a GT-I9000:
|
||||
|
||||
heimdall flash --repartition --resume --pit s1_odin_20100512.pit --FACTORYFS factoryfs.rfs --CACHE cache.rfs --DBDATA dbdata.rfs --IBL+PBL boot.bin --SBL Sbl.bin --PARAM param.lfs --KERNEL zImage --MODEM modem.bin
|
||||
|
||||
9. Heimdall will display the progress as it flashes so that you know things
|
||||
are working as they should.
|
||||
|
||||
|
||||
|
||||
How to Create a Heimdall Firmware Package:
|
||||
|
||||
Firstly, Heimdall's firmware package format is just a regular TAR archive
|
||||
compressed with gzip. The only two real requirements are that a valid
|
||||
firmware.xml must be included (refer to Appendix A) and you can only
|
||||
include files (no directories, links etc.) As such if you'd like there is
|
||||
nothing preventing you from creating Heimdall packages manually. Of course
|
||||
Heimdall Frontend provides a simple user interface that takes care of all
|
||||
the hard work for you.
|
||||
|
||||
There are two ways in which you can create a firmware package. You can
|
||||
create a package from scratch, or you can load an existing package, apply
|
||||
modifications and then save the package. Creating a package from scratch
|
||||
is the preferred approach, by taking this approach you're far less likely
|
||||
to run into file name length limitations. These are not Heimdall's own
|
||||
limitation but rather a limitation of the TAR archive format.
|
||||
|
||||
Before you can access Heimdall Frontend's firmware creation functionality
|
||||
(available from the "Create Package" tab) you must first specify which
|
||||
files will be included in your package, as well as a few flashing options
|
||||
i.e. Whether or not users should repartition when flashing. This
|
||||
information must be filled out from the "Flash" tab in exactly the same
|
||||
fashion you would provide information to flash your device (see "Performing
|
||||
a Custom Flash with Heimdall Frontend"). As mentioned above, it's not the
|
||||
preferred means, but you're able to load an existing package as a starting
|
||||
point for this information.
|
||||
|
||||
Once you've specified the files/partitions you wish to include in your
|
||||
firmware package the "Create Package" tab will become available. Clicking
|
||||
this tab will display additional information that you can include in your
|
||||
package. In order to continue you must fill out all sections except for the
|
||||
URLs section, which is optional. The following is a break-down of what all
|
||||
these options mean.
|
||||
|
||||
- General Firmware Information: -
|
||||
|
||||
Firmware Name - This is the name of your particular firmware. An
|
||||
example would be "Cyanogenmod".
|
||||
|
||||
Firmware Version - This is the version identifier for your package. Any
|
||||
valid string will be accepted although a the inclusion of decimal
|
||||
point version number is preferred i.e. "7.1". If it makes sense
|
||||
then feel free to append a text string like "RC1" or "Beta 1" to
|
||||
the decimal point version.
|
||||
|
||||
Platform Name - This is the name of the platform (or operating system)
|
||||
that your firmware is based on. In most cases this will simply be
|
||||
"Android".
|
||||
|
||||
Platform Version - This is the operating system version that your
|
||||
firmware is based on. Again decimal point version numbers are
|
||||
preferred over text, i.e. "2.3.4" is preferred over "Gingerbread".
|
||||
|
||||
|
||||
- Developers -
|
||||
|
||||
URLs (Optional):
|
||||
|
||||
Homepage - Here you can enter your personal URL or a URL particularly
|
||||
pertaining to the firmware being packaged. The URL must be well
|
||||
formed for it to work. An example of a well formed URL is
|
||||
"http://www.glassechidna.com.au/products/heimdall/". It is
|
||||
important to include "http://" in order to specify the protocol as
|
||||
other protocols such as "ftp://" are equally valid although
|
||||
unlikely to be used.
|
||||
|
||||
Donate - Here you can enter a URL that will link users to a page to
|
||||
make donations for the effort you've put into developing your
|
||||
firmware. Once again the URL must be well formed but there is no
|
||||
requirement on how your donation page should work. For instance
|
||||
both "http://www.glassechidna.com.au/donate/" and
|
||||
"http://forum.xda-developers.com/donatetome.php?u=2710388" are
|
||||
equally valid.
|
||||
|
||||
Developer Info:
|
||||
|
||||
Name - Here you can enter in the name of individual team members or a
|
||||
team name. Click "Add" and the developer will be added to the list
|
||||
on the right. If you make a mistake you can select a developer from
|
||||
the list and click "Remove". You can list as many developers as you
|
||||
like however visual constraints of the "Load Package" tab means
|
||||
only a few names will be visible. Where possible you may want to
|
||||
opt for team names over listing individual team members.
|
||||
|
||||
|
||||
- Supported Devices -
|
||||
|
||||
This section allows you to create a list of devices that are supported by
|
||||
your particular firmware. Although Heimdall isn't capable of enforcing this
|
||||
we strongly recommend you take this section seriously. If filled out
|
||||
correctly you could help save a number of accidental bricks!
|
||||
|
||||
Device Info:
|
||||
|
||||
Manufacturer - This is where you can enter the name of the manufacturer
|
||||
for a particular device. For now this will most likely be
|
||||
"Samsung".
|
||||
|
||||
Name - This is the human readable name for a particular device.
|
||||
"Galaxy S", "Galaxy S II", "Droid Charge", "Vibrant" and
|
||||
"Galaxy S (Telstra)" are all valid names. There are a lot of
|
||||
possible variations here so be as specific as you think is
|
||||
necessary.
|
||||
|
||||
Product Code - This is by far the most important bit of device
|
||||
information. Device names tend to be region specific and further
|
||||
subject to the whims of telecommunication companies and resellers.
|
||||
Product Codes (or product IDs) are designated by manufacturers and
|
||||
are generally the definitive means of referring to a particular
|
||||
device. Examples are "GT-I9000", "GT-I9100" and "SCH-I897". If
|
||||
you're unsure of a particular product code then both Google and
|
||||
GSMArena are your friends!
|
||||
|
||||
|
||||
After filling out all the necessary information the "Build" button will be
|
||||
enabled. If it's still disabled then you know you're missing some required
|
||||
information. In particular you must specify at least one developer and at
|
||||
least one supported device. Pressing the "Build" button will bring up a
|
||||
save dialogue where you must chose a file name for your particular package.
|
||||
Don't worry about specifying the ".tar.gz" extension Heimdall Frontend will
|
||||
take care of this automatically.
|
||||
|
||||
Once you've chosen a file name Heimdall Frontend will begin the process of
|
||||
building the firmware package. In doing so a valid firmware.xml file will
|
||||
be generated from the information entered. All files will be archived in a
|
||||
single TAR file then the TAR archive will be compressed via gzip
|
||||
compression. Compression will take a little while but you will see progress
|
||||
bars so you know the application hasn't hung. When the progress bars
|
||||
disappear you're finished making your package.
|
||||
|
||||
Congratulations! You're now ready to redistribute your firmware package
|
||||
online or by any means you see fit.
|
||||
|
||||
|
||||
|
||||
Appendix A - firmware.xml
|
||||
|
||||
The following details a part of the Heimdall Firmware Package format. This
|
||||
is only relevant to developers or advanced users who wish to create Heimdall
|
||||
Firmware Packages outside of Heimdall Frontend or in some way integrate support
|
||||
for the format in their own software.
|
||||
|
||||
|
||||
All Heimdall Firmware Packages must contain a file called firmware.xml. This
|
||||
file stores flash information and meta-data for the package as well as
|
||||
information about other files contained within the package.
|
||||
|
||||
The format is fairly straight-forward so it won't be explained in great detail.
|
||||
Nonetheless the following is an example of a valid firmware.xml file.
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<firmware version="1">
|
||||
<name>Test Firmware</name>
|
||||
<version>1.1</version>
|
||||
<platform>
|
||||
<name>Android</name>
|
||||
<version>2.3.4</version>
|
||||
</platform>
|
||||
<developers>
|
||||
<name>Benjamin Dobell</name>
|
||||
<name>Hedonism Bot</name>
|
||||
</developers>
|
||||
<url>http://www.glassechidna.com.au/</url>
|
||||
<donateurl>http://www.glassechidna.com.au/donate/</donateurl>
|
||||
<devices>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000</product>
|
||||
<name>Galaxy S</name>
|
||||
</device>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000T</product>
|
||||
<name>Galaxy S (Telstra)</name>
|
||||
</device>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000M</product>
|
||||
<name>Vibrant</name>
|
||||
</device>
|
||||
</devices>
|
||||
<pit>Nl3276-I9000 s1_odin_20100512.pit</pit>
|
||||
<repartition>0</repartition>
|
||||
<noreboot>0</noreboot>
|
||||
<files>
|
||||
<file>
|
||||
<id>0</id>
|
||||
<filename>gq3276-boot.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>24</id>
|
||||
<filename>Uh3276-cache.rfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>22</id>
|
||||
<filename>em3276-factoryfs.rfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>11</id>
|
||||
<filename>fl3276-modem.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>21</id>
|
||||
<filename>Xd3276-param.lfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>3</id>
|
||||
<filename>if3276-Sbl.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>6</id>
|
||||
<filename>cr3276-zImage</filename>
|
||||
</file>
|
||||
</files>
|
||||
</firmware>
|
||||
|
||||
|
||||
New lines need not be included and the order in which elements are specified
|
||||
does not need to match that of the above example.
|
||||
|
||||
One and only one <firmware> element must be included. The <firmware> element
|
||||
must also have a version attribute specified. The version must be parsable as
|
||||
an integer and indicates what version of the Heimdall Firmware Package
|
||||
specification the package adheres to.
|
||||
|
||||
All data is stored as strings, however a <file>'s <id> element must be parsable
|
||||
as an integer. The <id> value represents the partition ID (according to the
|
||||
specified PIT file) that the file should be flashed to.
|
||||
|
||||
A <firmware>'s <repartition> and <noreboot> elements must also be parsable as
|
||||
an integer. However, as they represent boolean values, a value of zero ("0")
|
||||
means false (or disabled) where as a non-zero value (typically "1") means true
|
||||
(or enabled).
|
||||
|
||||
File names are specified relative to the TAR archive in which firmware.xml and
|
||||
all other files are to be stored. Heimdall Firmware Packages do not support
|
||||
directories or links, as such file names should only be a name and not a path.
|
||||
|
||||
<url> and <donateurl> are the only optional elements, all other elements must
|
||||
be included.
|
||||
|
||||
|
||||
|
||||
Appendix B - Installing Heimdall Suite from Source
|
||||
|
||||
1. Open Terminal and install dependencies using Homebrew (http://brew.sh)
|
||||
|
||||
brew install libusb qt5 cmake
|
||||
|
||||
2. Build Heimdall & Heimdall Frontend
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DQt5Widgets_DIR=/usr/local/opt/qt5/lib/cmake/Qt5Widgets ..
|
||||
make
|
52
OSX/heimdall.kext/Contents/Info.plist
Executable file
52
OSX/heimdall.kext/Contents/Info.plist
Executable file
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key> <string>English</string>
|
||||
<key>CFBundleGetInfoString</key> <string>Heimdall Download Mode</string>
|
||||
<key>CFBundleIdentifier</key> <string>au.com.glassechidna.heimdall.usb_shield</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key> <string>6.0</string>
|
||||
<key>CFBundleName</key> <string>Heimdall Download Mode</string>
|
||||
<key>CFBundlePackageType</key> <string>KEXT</string>
|
||||
<key>CFBundleSignature</key> <string>????</string>
|
||||
<key>CFBundleVersion</key> <string>6.0</string>
|
||||
<key>IOKitPersonalities</key>
|
||||
<dict>
|
||||
<key>0x6001</key>
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key> <string>com.apple.driver.AppleUSBComposite</string>
|
||||
<key>IOClass</key> <string>AppleUSBComposite</string>
|
||||
<key>IOProbeScore</key> <integer>300000</integer>
|
||||
<key>IOProviderClass</key> <string>IOUSBDevice</string>
|
||||
<key>idVendor</key> <integer>1256</integer>
|
||||
<key>idProduct</key> <integer>26113</integer>
|
||||
<key>bcdDevice</key> <integer>256</integer>
|
||||
</dict>
|
||||
<key>0x685D</key>
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key> <string>com.apple.driver.AppleUSBComposite</string>
|
||||
<key>IOClass</key> <string>AppleUSBComposite</string>
|
||||
<key>IOProbeScore</key> <integer>300000</integer>
|
||||
<key>IOProviderClass</key> <string>IOUSBDevice</string>
|
||||
<key>idVendor</key> <integer>1256</integer>
|
||||
<key>idProduct</key> <integer>26717</integer>
|
||||
<key>bcdDevice</key> <integer>256</integer>
|
||||
</dict>
|
||||
<key>0x68C3</key>
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key> <string>com.apple.driver.AppleUSBComposite</string>
|
||||
<key>IOClass</key> <string>AppleUSBComposite</string>
|
||||
<key>IOProbeScore</key> <integer>300000</integer>
|
||||
<key>IOProviderClass</key> <string>IOUSBDevice</string>
|
||||
<key>idVendor</key> <integer>1256</integer>
|
||||
<key>idProduct</key> <integer>26819</integer>
|
||||
<key>bcdDevice</key> <integer>256</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>OSBundleCompatibleVersion</key> <string>1.8</string>
|
||||
<key>OSBundleLibraries</key>
|
||||
<dict>
|
||||
<key>com.apple.kpi.iokit</key> <string>8.0.0</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
BIN
OSX/heimdall.kext/Contents/_CodeSignature/CodeDirectory
Normal file
BIN
OSX/heimdall.kext/Contents/_CodeSignature/CodeDirectory
Normal file
Binary file not shown.
BIN
OSX/heimdall.kext/Contents/_CodeSignature/CodeRequirements
Normal file
BIN
OSX/heimdall.kext/Contents/_CodeSignature/CodeRequirements
Normal file
Binary file not shown.
105
OSX/heimdall.kext/Contents/_CodeSignature/CodeResources
Normal file
105
OSX/heimdall.kext/Contents/_CodeSignature/CodeResources
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict/>
|
||||
<key>files2</key>
|
||||
<dict/>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
BIN
OSX/heimdall.kext/Contents/_CodeSignature/CodeSignature
Normal file
BIN
OSX/heimdall.kext/Contents/_CodeSignature/CodeSignature
Normal file
Binary file not shown.
8
OSX/install-kext.sh
Executable file
8
OSX/install-kext.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
BASEDIR=$(dirname $0)
|
||||
echo 'Installing Driver...'
|
||||
sudo cp -R "$BASEDIR/heimdall.kext" /System/Library/Extensions
|
||||
sudo chmod -R 755 /System/Library/Extensions/heimdall.kext
|
||||
sudo chown -R root:wheel /System/Library/Extensions/heimdall.kext
|
||||
sudo kextload /System/Library/Extensions/heimdall.kext
|
||||
echo 'Installation complete. If Heimdall cannot recognise your device a reboot may be required.'
|
60
README.md
Normal file
60
README.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
[Original source](https://github.com/Benjamin-Dobell/Heimdall) by Benjamin Dobell
|
||||
|
||||
UPDATE: It was modified by maxmoon in 2022 to flash custom firmware like [LineageOS](https://download.lineageos.org) on old devices (there was a bug).
|
||||
|
||||
[Here](https://publish.ministryofinternet.eu/utopify-org/flashing-old-smartphones-with-custom-firmware) is a step by step guide on how to flash old smartphones with it, like a **Samsung Galaxy S5 (SM-G900F)**.
|
||||
|
||||
---
|
||||
|
||||
**The following lines are from the original README.md**
|
||||
|
||||
---
|
||||
|
||||
# Heimdall
|
||||
|
||||
Heimdall is a cross-platform open-source tool suite used to flash firmware (aka ROMs) onto Samsung mobile devices.
|
||||
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Officially, AMD64/x86-64 (64-bit) or x86 (32-bit) computers running:
|
||||
|
||||
* Linux
|
||||
* macOS
|
||||
* Windows (XP, Vista, 7 etc.)
|
||||
|
||||
However, several third-parties have reported success running Heimdall on ARM chipsets
|
||||
(in particular Raspberry Pi), as well as additional operating systems such as FreeBSD.
|
||||
|
||||
## How does Heimdall work?
|
||||
|
||||
Heimdall connects to a mobile device over USB and interacts with low-level software
|
||||
running on the device, known as Loke. Loke and Heimdall communicate via the custom
|
||||
Samsung-developed protocol typically referred to as the 'Odin 3 protocol'.
|
||||
|
||||
USB communication in Heimdall is handled by the popular open-source USB library, [libusb](http://libusb.info).
|
||||
|
||||
## Free & Open Source
|
||||
|
||||
Heimdall is both free and open source. It is licensed under the MIT license (see LICENSE).
|
||||
|
||||
Heimdall is maintained and predominantly developed by [Glass Echidna](http://glassechidna.com.au/),
|
||||
a _tiny_ independent software development company. If you appreciate our work and would like
|
||||
to support future development please consider making a [donation](http://glassechidna.com.au/donate/).
|
||||
|
||||
## Documentation
|
||||
|
||||
For more details about how to compile and install Heimdall please refer to the
|
||||
appropriate platform specific README:
|
||||
|
||||
#### Linux
|
||||
|
||||
- Linux/README ([online](https://raw.githubusercontent.com/Benjamin-Dobell/Heimdall/master/Linux/README))
|
||||
|
||||
#### OS X
|
||||
|
||||
- OSX/README.txt ([online](https://raw.githubusercontent.com/Benjamin-Dobell/Heimdall/master/OSX/README.txt))
|
||||
|
||||
#### Windows
|
||||
|
||||
- Win32/README.txt ([online](https://raw.githubusercontent.com/Benjamin-Dobell/Heimdall/master/Win32/README.txt))
|
BIN
Win32/Drivers/zadig.exe
Normal file
BIN
Win32/Drivers/zadig.exe
Normal file
Binary file not shown.
547
Win32/README.txt
Normal file
547
Win32/README.txt
Normal file
|
@ -0,0 +1,547 @@
|
|||
Heimdall (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
http://www.glassechidna.com.au/products/heimdall/
|
||||
|
||||
DISCLAIMER:
|
||||
|
||||
This software attempts to flash your Galaxy S device. The very nature of
|
||||
flashing is dangerous. As with all flashing software, Heimdall has the
|
||||
potential to damage (brick) your device if not used carefully. If you're
|
||||
concerned, don't use this software. Flashing ROMs onto your device may also
|
||||
void your warranty. Benjamin Dobell and Glass Echidna are not responsible
|
||||
for the result of your actions.
|
||||
|
||||
|
||||
These instructions were written for Windows 7 / Vista / Server 2008 however the
|
||||
procedure should be essentially the same for all supported versions of
|
||||
Windows (XP onwards).
|
||||
|
||||
|
||||
Driver Installation Instructions:
|
||||
|
||||
1. Put your device into download mode and plug it in.
|
||||
|
||||
2. Run zadig.exe included in the Drivers subdirectory.
|
||||
|
||||
3. From the menu chose Options -> List All Devices.
|
||||
|
||||
4. From the USB Device list chose "Samsung USB Composite DEvice".
|
||||
|
||||
5. Press "Install Driver", click "Yes" to the prompt and if you receive
|
||||
a message about being unable to verify the publisher of the driver
|
||||
click "Install this driver software anyway".
|
||||
|
||||
6. Done
|
||||
|
||||
|
||||
|
||||
Driver Uninstallation Instructions:
|
||||
|
||||
1. Put your device into download mode by holding Volume Down + Home + Power.
|
||||
|
||||
2. Plug your phone into your PC.
|
||||
|
||||
3. Open up Device Manager on your PC (Control Panel -> System -> Device Manager).
|
||||
|
||||
4. Under "Libusb (WinUSB) devices" right click on "Samsung USB Composite Device" and chose Properties.
|
||||
|
||||
5. Go to the Driver tab and select Update Driver.
|
||||
|
||||
6. Chose to browse your computer for the driver.
|
||||
|
||||
7. Chose to pick from a list of devices drivers on your computer.
|
||||
|
||||
8. Pick the original Samsung Composite driver, press next and then follow the prompts.
|
||||
|
||||
9. Done
|
||||
|
||||
|
||||
|
||||
Flashing Heimdall Firmware Package with Heimdall Frontend:
|
||||
|
||||
As of Heimdall Frontend 1.3 there are now two main ways to flash a ROM from
|
||||
Heimdall Frontend. The simpler and preferred option is to download a
|
||||
Heimdall Firmware Package and follow the following steps.
|
||||
|
||||
|
||||
1. Fully charge your device (use the wall charger as it's faster).
|
||||
|
||||
2. Open the Heimdall Frontend (heimdall-frontend) executable.
|
||||
|
||||
3. From the "Load Package" tab, under the "Heimdall Firmware Package"
|
||||
section click the "Browse" button.
|
||||
|
||||
4. Use the dialogue that appears to navigate to, and select, the Heimdall
|
||||
firmware package that you wish to flash.
|
||||
|
||||
5. You will see progress bars appear as the package is decompressed and
|
||||
extracted.
|
||||
|
||||
When the package has finished being decompressed you should see
|
||||
information about the particular firmware package that has been
|
||||
selected.
|
||||
|
||||
6. Verify that your device is listed under "Supported Devices". If it's not
|
||||
then STOP immediately! DO NOT flash this firmware to your device!
|
||||
Instead search for an appropriate firmware package for your device.
|
||||
|
||||
If you believe there is a mistake and your device is actually
|
||||
supported please get in contact with the firmware developer (not Glass
|
||||
Echidna!) and ask them to rectify the issue. If the developer provided
|
||||
a URL you may be able to contact them by pressing the "Homepage" button.
|
||||
|
||||
7. If you've verified your device is supported you may continue to press
|
||||
the "Load / Customise" button.
|
||||
|
||||
8. You should now be looking at the "Flash" tab. If not verify that you did
|
||||
in fact push the "Load / Customise" button.
|
||||
|
||||
Generally, you won't NEED or WANT to customise a firmware package! In
|
||||
which case you can safely move on to step 9.
|
||||
|
||||
Nonetheless, the "Flash" tab provides you with a means to customise the
|
||||
firmware package before flashing it to your device. See "Performing a
|
||||
Custom Flash with Heimdall Frontend" for more details.
|
||||
|
||||
9. Put your Galaxy S device into download mode and plug it in to your PC.
|
||||
|
||||
Download mode can be accessed several different ways depending on your
|
||||
particular device model. If you're unsure how to do this please search
|
||||
online for the appropriate method.
|
||||
|
||||
10. Press the "Start" button.
|
||||
|
||||
11. Heimdall Frontend will display the progress and inform you when the
|
||||
flash is complete.
|
||||
|
||||
If something went wrong i.e. your device wasn't detected because it
|
||||
wasn't in download mode, then the status section will let you know the
|
||||
cause of the problem.
|
||||
|
||||
|
||||
|
||||
Performing a Custom Flash with Heimdall Frontend:
|
||||
|
||||
This is the advanced means of flashing firmware to your device.
|
||||
|
||||
If you're not an advanced user or a developer, in the event that a Heimdall
|
||||
Firmware Package doesn't exist for the particular firmware (or files) that
|
||||
you wish to flash, then I strongly recommend you get in touch with developer
|
||||
of the firmware (or files) and politely ask them to create a Heimdall
|
||||
Firmware Package for you. In doing so then you don't have to worry about
|
||||
making mistakes due to inexperience.
|
||||
|
||||
If you're looking to customise an existing Heimdall Firmware Package then
|
||||
follow steps 1-8 of "Flashing Heimdall Firmware Package with Heimdall
|
||||
Frontend" then start from below with step 5.
|
||||
|
||||
|
||||
1. Fully charge your device (use the wall charger as it's faster).
|
||||
|
||||
2. Download a decrypted device ROM or a Heimdall Firmware Package
|
||||
and extract everything to the one directory.
|
||||
|
||||
3. If the ROM is not a Heimdall Firmware Package it may instead be provided
|
||||
as multiple archives (nested or otherwise), extract them all to the same
|
||||
location.
|
||||
|
||||
NOTE: If you want to use the CSC then extract it last.
|
||||
|
||||
3. Open the Heimdall Frontend (heimdall-frontend) executable.
|
||||
|
||||
4. Select the "Flash" tab. From the "Flash" tab you're able to completely
|
||||
customise a flash.
|
||||
|
||||
5. Before you can chose which partitions you want to flash with particular
|
||||
files you MUST first select a PIT file. To do this click the "Browse"
|
||||
button in the "PIT" section. This will open a dialogue allowing you to
|
||||
navigate to and select a valid PIT (.pit) file.
|
||||
|
||||
If you do not already have a valid PIT file stored on your computer you
|
||||
can download your device's PIT file from the "Utilities" tab.
|
||||
|
||||
6. If a valid PIT file has been selected then "Add" button below the
|
||||
"Partitions (Files)" list-box will become enabled. Press this button to
|
||||
add a partition to your flash.
|
||||
|
||||
7. When you first add a partition you will see the "Partition Name" and
|
||||
"Partition ID" be populated with information. Use the "Partition Name"
|
||||
drop down to select which partition you wish to flash. "Partition ID"
|
||||
will automatically update and is never directly editable.
|
||||
|
||||
8. You must then select a file to flash to the partition that you just
|
||||
specified using the "Browse" button under the "File / Partition". You
|
||||
will not be able to flash, create a firmware package or add another
|
||||
partition until you have selected a file. However, you're still able to
|
||||
press the "Remove" button if you've decided not to flash the partition
|
||||
you've just specified.
|
||||
|
||||
9. When you've specified a file name then you'll be able to see the updated
|
||||
information in the partition list to the right. You can select any
|
||||
partition from this list and customise it as you see fit.
|
||||
|
||||
You can also remove a partition from the list by selecting it and
|
||||
clicking the "Remove" button. Removing a partition from the list doesn't
|
||||
remove it from your device, it simply means it will not be flashed.
|
||||
|
||||
10. Repeat steps 7-9 as often as needed to specify all the partitions/files
|
||||
that you wish to flash.
|
||||
|
||||
11. Now you can chose whether you would like to repartition your device as
|
||||
well as whether you would like to prevent the device rebooting once a
|
||||
flash has been completed. These options can be enabled or disabled by
|
||||
toggling the "Repartition" and "No Reboot" check-boxes.
|
||||
|
||||
In the general case you will only need to enable repartition if you wish
|
||||
to change the PIT file on your device. Keep in mind that repartitioning
|
||||
will wipe your device!
|
||||
|
||||
The "No Reboot" option is rarely required. It's mostly in place so you
|
||||
can manually boot straight into recovery mode after a flash (rather than
|
||||
booting up normally).
|
||||
|
||||
12. If you've added at least one partition to your flash (and selected a
|
||||
file for that partition) then the "Start" button will be enabled. Press
|
||||
the "Start" button to begin the flashing process.
|
||||
|
||||
You may notice that the "Create Package" tab becomes available at the
|
||||
whenever the "Start" button becomes available. From this tab you're able
|
||||
to create a reusable, redistributable Heimdall Firmware Package with the
|
||||
files and partitions you just selected. See "How to Create a Heimdall
|
||||
Firmware Package" for details.
|
||||
|
||||
13. Heimdall Frontend will display the progress and inform you when the
|
||||
flash is complete.
|
||||
|
||||
If something went wrong i.e. your device wasn't detected because it
|
||||
wasn't in download mode, then the status section will let you know the
|
||||
cause of the problem.
|
||||
|
||||
|
||||
|
||||
Flashing Firmware from Command Line:
|
||||
|
||||
1. Fully charge your phone (use the wall charger as it's faster).
|
||||
|
||||
2. Download a decrypted device ROM or a Heimdall Firmware Package
|
||||
and extract everything to the one directory.
|
||||
|
||||
3. If the ROM is not a Heimdall Firmware Package it may instead be provided
|
||||
as multiple archives (nested or otherwise), extract them all to the same
|
||||
location.
|
||||
|
||||
NOTE: If you want to use the CSC then extract it last. If you're asked
|
||||
to overwrite files then do so.
|
||||
|
||||
4. Put your Galaxy S device into download mode and plug it in..
|
||||
|
||||
5. Open command prompt and navigate to the directory where you installed
|
||||
heimdall.
|
||||
|
||||
NOTE: Adding Heimdall to your PATH variable will allow you to run
|
||||
Heimdall from any directory.
|
||||
|
||||
6. Type the following to list all the functionality Heimdall supports:
|
||||
|
||||
heimdall help
|
||||
|
||||
7. Before flashing, you must first know the names of the partitions you
|
||||
wish to flash. These can be obtained by executing:
|
||||
|
||||
heimdall print-pit --no-reboot
|
||||
|
||||
The inclusion of --no-reboot ensures the phone will not reboot after PIT
|
||||
file has been downloaded and displayed. After executing a command with
|
||||
the --no-reboot argument, the next command should include the --resume
|
||||
argument.
|
||||
|
||||
NOTE: You can still safely reboot your phone manually (with the power
|
||||
button) after executing --no-reboot commands.
|
||||
|
||||
8. Use the help and print-pit output to construct a command with all the
|
||||
file you want to flash.
|
||||
|
||||
Here is an example that does a full flash and repartition on a GT-I9000:
|
||||
|
||||
heimdall flash --repartition --resume --pit s1_odin_20100512.pit --FACTORYFS factoryfs.rfs --CACHE cache.rfs --DBDATA dbdata.rfs --IBL+PBL boot.bin --SBL Sbl.bin --PARAM param.lfs --KERNEL zImage --MODEM modem.bin
|
||||
|
||||
NOTE: The above command assumes the files specified are installed in the
|
||||
same directory as Heimdall.
|
||||
|
||||
9. Heimdall will display the progress as it flashes so that you know things
|
||||
are working as they should.
|
||||
|
||||
|
||||
|
||||
How to Create a Heimdall Firmware Package:
|
||||
|
||||
Firstly, Heimdall's firmware package format is just a regular TAR archive
|
||||
compressed with gzip. The only two real requirements are that a valid
|
||||
firmware.xml must be included (refer to Appendix A) and you can only
|
||||
include files (no directories, links etc.) As such if you'd like there is
|
||||
nothing preventing you from creating Heimdall packages manually. Of course
|
||||
Heimdall Frontend provides a simple user interface that takes care of all
|
||||
the hard work for you.
|
||||
|
||||
There are two ways in which you can create a firmware package. You can
|
||||
create a package from scratch, or you can load an existing package, apply
|
||||
modifications and then save the package. Creating a package from scratch
|
||||
is the preferred approach, by taking this approach you're far less likely
|
||||
to run into file name length limitations. These are not Heimdall's own
|
||||
limitation but rather a limitation of the TAR archive format.
|
||||
|
||||
Before you can access Heimdall Frontend's firmware creation functionality
|
||||
(available from the "Create Package" tab) you must first specify which
|
||||
files will be included in your package, as well as a few flashing options
|
||||
i.e. Whether or not users should repartition when flashing. This
|
||||
information must be filled out from the "Flash" tab in exactly the same
|
||||
fashion you would provide information to flash your device (see "Performing
|
||||
a Custom Flash with Heimdall Frontend"). As mentioned above, it's not the
|
||||
preferred means, but you're able to load an existing package as a starting
|
||||
point for this information.
|
||||
|
||||
Once you've specified the files/partitions you wish to include in your
|
||||
firmware package the "Create Package" tab will become available. Clicking
|
||||
this tab will display additional information that you can include in your
|
||||
package. In order to continue you must fill out all sections except for the
|
||||
URLs section, which is optional. The following is a break-down of what all
|
||||
these options mean.
|
||||
|
||||
- General Firmware Information: -
|
||||
|
||||
Firmware Name - This is the name of your particular firmware. An
|
||||
example would be "Cyanogenmod".
|
||||
|
||||
Firmware Version - This is the version identifier for your package. Any
|
||||
valid string will be accepted although a the inclusion of decimal
|
||||
point version number is preferred i.e. "7.1". If it makes sense
|
||||
then feel free to append a text string like "RC1" or "Beta 1" to
|
||||
the decimal point version.
|
||||
|
||||
Platform Name - This is the name of the platform (or operating system)
|
||||
that your firmware is based on. In most cases this will simply be
|
||||
"Android".
|
||||
|
||||
Platform Version - This is the operating system version that your
|
||||
firmware is based on. Again decimal point version numbers are
|
||||
preferred over text, i.e. "2.3.4" is preferred over "Gingerbread".
|
||||
|
||||
|
||||
- Developers -
|
||||
|
||||
URLs (Optional):
|
||||
|
||||
Homepage - Here you can enter your personal URL or a URL particularly
|
||||
pertaining to the firmware being packaged. The URL must be well
|
||||
formed for it to work. An example of a well formed URL is
|
||||
"http://www.glassechidna.com.au/products/heimdall/". It is
|
||||
important to include "http://" in order to specify the protocol as
|
||||
other protocols such as "ftp://" are equally valid although
|
||||
unlikely to be used.
|
||||
|
||||
Donate - Here you can enter a URL that will link users to a page to
|
||||
make donations for the effort you've put into developing your
|
||||
firmware. Once again the URL must be well formed but there is no
|
||||
requirement on how your donation page should work. For instance
|
||||
both "http://www.glassechidna.com.au/donate/" and
|
||||
"http://forum.xda-developers.com/donatetome.php?u=2710388" are
|
||||
equally valid.
|
||||
|
||||
Developer Info:
|
||||
|
||||
Name - Here you can enter in the name of individual team members or a
|
||||
team name. Click "Add" and the developer will be added to the list
|
||||
on the right. If you make a mistake you can select a developer from
|
||||
the list and click "Remove". You can list as many developers as you
|
||||
like however visual constraints of the "Load Package" tab means
|
||||
only a few names will be visible. Where possible you may want to
|
||||
opt for team names over listing individual team members.
|
||||
|
||||
|
||||
- Supported Devices -
|
||||
|
||||
This section allows you to create a list of devices that are supported by
|
||||
your particular firmware. Although Heimdall isn't capable of enforcing this
|
||||
we strongly recommend you take this section seriously. If filled out
|
||||
correctly you could help save a number of accidental bricks!
|
||||
|
||||
Device Info:
|
||||
|
||||
Manufacturer - This is where you can enter the name of the manufacturer
|
||||
for a particular device. For now this will most likely be
|
||||
"Samsung".
|
||||
|
||||
Name - This is the human readable name for a particular device.
|
||||
"Galaxy S", "Galaxy S II", "Droid Charge", "Vibrant" and
|
||||
"Galaxy S (Telstra)" are all valid names. There are a lot of
|
||||
possible variations here so be as specific as you think is
|
||||
necessary.
|
||||
|
||||
Product Code - This is by far the most important bit of device
|
||||
information. Device names tend to be region specific and further
|
||||
subject to the whims of telecommunication companies and resellers.
|
||||
Product Codes (or product IDs) are designated by manufacturers and
|
||||
are generally the definitive means of referring to a particular
|
||||
device. Examples are "GT-I9000", "GT-I9100" and "SCH-I897". If
|
||||
you're unsure of a particular product code then both Google and
|
||||
GSMArena are your friends!
|
||||
|
||||
|
||||
After filling out all the necessary information the "Build" button will be
|
||||
enabled. If it's still disabled then you know you're missing some required
|
||||
information. In particular you must specify at least one developer and at
|
||||
least one supported device. Pressing the "Build" button will bring up a
|
||||
save dialogue where you must chose a file name for your particular package.
|
||||
Don't worry about specifying the ".tar.gz" extension Heimdall Frontend will
|
||||
take care of this automatically.
|
||||
|
||||
Once you've chosen a file name Heimdall Frontend will begin the process of
|
||||
building the firmware package. In doing so a valid firmware.xml file will
|
||||
be generated from the information entered. All files will be archived in a
|
||||
single TAR file then the TAR archive will be compressed via gzip
|
||||
compression. Compression will take a little while but you will see progress
|
||||
bars so you know the application hasn't hung. When the progress bars
|
||||
disappear you're finished making your package.
|
||||
|
||||
Congratulations! You're now ready to redistribute your firmware package
|
||||
online or by any means you see fit.
|
||||
|
||||
|
||||
|
||||
Appendix A - firmware.xml
|
||||
|
||||
The following details a part of the Heimdall Firmware Package format. This
|
||||
is only relevant to developers or advanced users who wish to create Heimdall
|
||||
Firmware Packages outside of Heimdall Frontend or in some way integrate support
|
||||
for the format in their own software.
|
||||
|
||||
|
||||
All Heimdall Firmware Packages must contain a file called firmware.xml. This
|
||||
file stores flash information and meta-data for the package as well as
|
||||
information about other files contained within the package.
|
||||
|
||||
The format is fairly straight-forward so it won't be explained in great detail.
|
||||
Nonetheless the following is an example of a valid firmware.xml file.
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<firmware version="1">
|
||||
<name>Test Firmware</name>
|
||||
<version>1.1</version>
|
||||
<platform>
|
||||
<name>Android</name>
|
||||
<version>2.3.4</version>
|
||||
</platform>
|
||||
<developers>
|
||||
<name>Benjamin Dobell</name>
|
||||
<name>Hedonism Bot</name>
|
||||
</developers>
|
||||
<url>http://www.glassechidna.com.au/</url>
|
||||
<donateurl>http://www.glassechidna.com.au/donate/</donateurl>
|
||||
<devices>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000</product>
|
||||
<name>Galaxy S</name>
|
||||
</device>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000T</product>
|
||||
<name>Galaxy S (Telstra)</name>
|
||||
</device>
|
||||
<device>
|
||||
<manufacturer>Samsung</manufacturer>
|
||||
<product>GT-I9000M</product>
|
||||
<name>Vibrant</name>
|
||||
</device>
|
||||
</devices>
|
||||
<pit>Nl3276-I9000 s1_odin_20100512.pit</pit>
|
||||
<repartition>0</repartition>
|
||||
<noreboot>0</noreboot>
|
||||
<files>
|
||||
<file>
|
||||
<id>0</id>
|
||||
<filename>gq3276-boot.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>24</id>
|
||||
<filename>Uh3276-cache.rfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>22</id>
|
||||
<filename>em3276-factoryfs.rfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>11</id>
|
||||
<filename>fl3276-modem.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>21</id>
|
||||
<filename>Xd3276-param.lfs</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>3</id>
|
||||
<filename>if3276-Sbl.bin</filename>
|
||||
</file>
|
||||
<file>
|
||||
<id>6</id>
|
||||
<filename>cr3276-zImage</filename>
|
||||
</file>
|
||||
</files>
|
||||
</firmware>
|
||||
|
||||
|
||||
New lines need not be included and the order in which elements are specified
|
||||
does not need to match that of the above example.
|
||||
|
||||
One and only one <firmware> element must be included. The <firmware> element
|
||||
must also have a version attribute specified. The version must be parsable as
|
||||
an integer and indicates what version of the Heimdall Firmware Package
|
||||
specification the package adheres to.
|
||||
|
||||
All data is stored as strings, however a <file>'s <id> element must be parsable
|
||||
as an integer. The <id> value represents the partition ID (according to the
|
||||
specified PIT file) that the file should be flashed to.
|
||||
|
||||
A <firmware>'s <repartition> and <noreboot> elements must also be parsable as
|
||||
an integer. However, as they represent boolean values, a value of zero ("0")
|
||||
means false (or disabled) where as a non-zero value (typically "1") means true
|
||||
(or enabled).
|
||||
|
||||
File names are specified relative to the TAR archive in which firmware.xml and
|
||||
all other files are to be stored. Heimdall Firmware Packages do not support
|
||||
directories or links, as such file names should only be a name and not a path.
|
||||
|
||||
<url> and <donateurl> are the only optional elements, all other elements must
|
||||
be included.
|
||||
|
||||
|
||||
|
||||
Appendix B - Installing Heimdall Suite from Source
|
||||
|
||||
Heimdall and Heimdall Frontend both utilise CMake for managing the build
|
||||
process. CMake can generate files for various build systems including GNU
|
||||
Make and Visual Studio. However, official packages are compiled with GNU
|
||||
Make and MinGW-W64 GCC/G++.
|
||||
|
||||
NOTE: Official builds use MinGW-W64 simply because on-going cross-platform
|
||||
development is simpler when using just the one IDE (Jetbrain's CLion)
|
||||
and similar toolchains.
|
||||
|
||||
1. Setup a MinGW-W64 build environment by utilising MSYS2:
|
||||
|
||||
http://msys2.github.io/
|
||||
|
||||
2. After installing MSYS2 a command prompt will launch, enter:
|
||||
|
||||
Pacman -Syu
|
||||
Pacman -S mingw-w64-x86_64 mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-libusb mingw-w64-x86_64-qt5-static make
|
||||
|
||||
3. Add the MinGW-W64 binaries to your PATH environment variable:
|
||||
|
||||
export PATH="/mingw64/bin:$PATH"
|
||||
|
||||
4. Build Heimdall & Heimdall Frontend
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release -DQt5Widgets_DIR=/c/msys64/mingw64/qt5-static/lib/cmake/Qt5Widgets ..
|
||||
make
|
36
cmake/Findlibusb.cmake
Normal file
36
cmake/Findlibusb.cmake
Normal file
|
@ -0,0 +1,36 @@
|
|||
find_path(LIBUSB_INCLUDE_DIR
|
||||
NAMES
|
||||
libusb.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/usr/include
|
||||
PATH_SUFFIXES
|
||||
libusb-1.0
|
||||
)
|
||||
|
||||
if (libusb_USE_STATIC_LIBS AND NOT MSVC)
|
||||
set (LIBUSB_LIB_PREFIX "lib" CACHE INTERNAL "libusb library name prefix passed to find_library")
|
||||
set (LIBUSB_LIB_SUFFIX ".a" CACHE INTERNAL "libusb library name suffix passed to find_library")
|
||||
else (libusb_USE_STATIC_LIBS AND NOT MSVC)
|
||||
set (LIBUSB_LIB_PREFIX "" CACHE INTERNAL "libusb library name prefix passed to find_library")
|
||||
set (LIBUSB_LIB_SUFFIX "" CACHE INTERNAL "libusb library name suffix passed to find_library")
|
||||
endif (libusb_USE_STATIC_LIBS AND NOT MSVC)
|
||||
|
||||
find_library(LIBUSB_LIBRARY
|
||||
NAMES
|
||||
${LIBUSB_LIB_PREFIX}usb-1.0${LIBUSB_LIB_SUFFIX} ${LIBUSB_LIB_PREFIX}usb${LIBUSB_LIB_SUFFIX}
|
||||
PATHS
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libusb REQUIRED_VARS LIBUSB_LIBRARY LIBUSB_INCLUDE_DIR)
|
||||
|
||||
if (LIBUSB_FOUND)
|
||||
set(LIBUSB_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIR})
|
||||
set(LIBUSB_LIBRARIES ${LIBUSB_LIBRARY})
|
||||
mark_as_advanced(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARY)
|
||||
endif (LIBUSB_FOUND)
|
15
cmake/LargeFiles.c
Normal file
15
cmake/LargeFiles.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define VALID_ARRAY_LENGTH 1
|
||||
#define INVALID_ARRAY_LENGTH -1
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
int a[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? VALID_ARRAY_LENGTH : INVALID_ARRAY_LENGTH];
|
||||
off_t offset = ftello(NULL);
|
||||
fseeko(NULL, offset, SEEK_SET);
|
||||
return 0;
|
||||
}
|
107
cmake/LargeFiles.cmake
Normal file
107
cmake/LargeFiles.cmake
Normal file
|
@ -0,0 +1,107 @@
|
|||
macro(test_large_files VARIABLE USE_64_SUFFIX)
|
||||
if(NOT DEFINED ${VARIABLE})
|
||||
message(STATUS "Checking if large (64-bit) file support is available...")
|
||||
|
||||
if(USE_64_SUFFIX)
|
||||
set(SUFFIX_64 "64")
|
||||
else(USE_64_SUFFIX)
|
||||
set(SUFFIX_64 "")
|
||||
endif(USE_64_SUFFIX)
|
||||
|
||||
# First try without any macros defined
|
||||
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c"
|
||||
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
|
||||
|
||||
if(VERBOSE_LARGE_FILES)
|
||||
message(STATUS "Large file output (no special flags):\n${TRY_LARGE_FILES_OUTPUT}")
|
||||
endif(VERBOSE_LARGE_FILES)
|
||||
|
||||
if(NOT LARGE_FILES_SUPPORTED)
|
||||
# Try with C macro _FILE_OFFSET_BITS=64
|
||||
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c"
|
||||
COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64"
|
||||
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
|
||||
|
||||
if(VERBOSE_LARGE_FILES)
|
||||
message(STATUS "Large file output (_FILE_OFFSET_BITS=64):\n${TRY_LARGE_FILES_OUTPUT}")
|
||||
endif(VERBOSE_LARGE_FILES)
|
||||
|
||||
if(LARGE_FILES_SUPPORTED)
|
||||
set(_FILE_OFFSET_BITS=64 CACHE INTERNAL "C macro _FILE_OFFSET_BITS=64 is required for 64-bit file support")
|
||||
endif(LARGE_FILES_SUPPORTED)
|
||||
endif(NOT LARGE_FILES_SUPPORTED)
|
||||
|
||||
if(NOT LARGE_FILES_SUPPORTED)
|
||||
# Try with C macro _LARGEFILE_SOURCE
|
||||
|
||||
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c"
|
||||
COMPILE_DEFINITIONS "-D_LARGEFILE${SUFFIX_64}_SOURCE"
|
||||
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
|
||||
|
||||
if(VERBOSE_LARGE_FILES)
|
||||
message(STATUS "Large file output (_LARGEFILE${SUFFIX_64}_SOURCE):\n${TRY_LARGE_FILES_OUTPUT}")
|
||||
endif(VERBOSE_LARGE_FILES)
|
||||
|
||||
if(LARGE_FILES_SUPPORTED)
|
||||
set(_LARGEFILE${SUFFIX_64}_SOURCE=1 CACHE INTERNAL "C macro _LARGEFILE${SUFFIX_64}_SOURCE is required for 64-bit file support")
|
||||
endif(LARGE_FILES_SUPPORTED)
|
||||
endif(NOT LARGE_FILES_SUPPORTED)
|
||||
|
||||
if(NOT LARGE_FILES_SUPPORTED)
|
||||
# Try with both C macro _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE
|
||||
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c"
|
||||
COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" "-D_LARGEFILE${SUFFIX_64}_SOURCE"
|
||||
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
|
||||
|
||||
if(VERBOSE_LARGE_FILES)
|
||||
message(STATUS "Large file output (_FILE_OFFSET_BITS=64 and _LARGEFILE${SUFFIX_64}_SOURCE):\n${TRY_LARGE_FILES_OUTPUT}")
|
||||
endif(VERBOSE_LARGE_FILES)
|
||||
|
||||
if(LARGE_FILES_SUPPORTED)
|
||||
set(_FILE_OFFSET_BITS=64 CACHE INTERNAL "C macro _FILE_OFFSET_BITS=64 is required for 64-bit file support")
|
||||
set(_LARGEFILE${SUFFIX_64}_SOURCE=1 CACHE INTERNAL "C macro _LARGEFILE${SUFFIX_64}_SOURCE is required for 64-bit file support")
|
||||
endif(LARGE_FILES_SUPPORTED)
|
||||
endif(NOT LARGE_FILES_SUPPORTED)
|
||||
|
||||
if(NOT LARGE_FILES_SUPPORTED)
|
||||
# Maybe we are using the Windows C standard library
|
||||
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_MODULE_PATH}/LargeFilesWindows.c")
|
||||
endif(NOT LARGE_FILES_SUPPORTED)
|
||||
|
||||
if(LARGE_FILES_SUPPORTED)
|
||||
message(STATUS "Checking if large (64-bit) file support is available - yes")
|
||||
set(${VARIABLE} 1 CACHE INTERNAL "Is large file support available?")
|
||||
else(LARGE_FILES_SUPPORTED)
|
||||
message(STATUS "Checking if large (64-bit) file support is available - no")
|
||||
set(${VARIABLE} 0 CACHE INTERNAL "Is large file support available?")
|
||||
endif(LARGE_FILES_SUPPORTED)
|
||||
endif(NOT DEFINED ${VARIABLE})
|
||||
endmacro(test_large_files VARIABLE USE_64_SUFFIX)
|
||||
|
||||
macro(use_large_files TARGET USE_64_SUFFIX)
|
||||
test_large_files(USING_LARGE_FILES ${USE_64_SUFFIX})
|
||||
|
||||
if(USING_LARGE_FILES)
|
||||
if(DEFINED _FILE_OFFSET_BITS)
|
||||
set_property(TARGET ${TARGET}
|
||||
APPEND PROPERTY COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}")
|
||||
endif(DEFINED _FILE_OFFSET_BITS)
|
||||
|
||||
if(DEFINED _LARGEFILE_SOURCE)
|
||||
set_property(TARGET ${TARGET}
|
||||
APPEND PROPERTY COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE")
|
||||
endif(DEFINED _LARGEFILE_SOURCE)
|
||||
|
||||
if(DEFINED _LARGEFILE64_SOURCE)
|
||||
set_property(TARGET ${TARGET}
|
||||
APPEND PROPERTY COMPILE_DEFINITIONS "-D_LARGEFILE64_SOURCE")
|
||||
endif(DEFINED _LARGEFILE64_SOURCE)
|
||||
else(USING_LARGE_FILES)
|
||||
message(FATAL_ERROR "Large file support not available")
|
||||
endif(USING_LARGE_FILES)
|
||||
endmacro(use_large_files TARGET USE_64_SUFFIX)
|
16
cmake/LargeFiles64.c
Normal file
16
cmake/LargeFiles64.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define VALID_ARRAY_LENGTH 1
|
||||
#define INVALID_ARRAY_LENGTH -1
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
int a[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? VALID_ARRAY_LENGTH : INVALID_ARRAY_LENGTH];
|
||||
off64_t offset = ftello64(NULL);
|
||||
fseeko64(NULL, offset, SEEK_SET);
|
||||
return 0;
|
||||
}
|
8
cmake/LargeFilesWindows.c
Normal file
8
cmake/LargeFilesWindows.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
__int64 off = 0;
|
||||
_fseeki64(NULL, off, SEEK_SET);
|
||||
return 0;
|
||||
}
|
56
heimdall-frontend/CMakeLists.txt
Normal file
56
heimdall-frontend/CMakeLists.txt
Normal file
|
@ -0,0 +1,56 @@
|
|||
cmake_minimum_required(VERSION 2.8.4)
|
||||
|
||||
project(heimdall-frontend)
|
||||
|
||||
set(LIBPIT_INCLUDE_DIRS
|
||||
../libpit/source)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON) # moc files are generated in build (current) directory
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
|
||||
|
||||
if(MINGW)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
|
||||
endif(MINGW)
|
||||
|
||||
include_directories(${LIBPIT_INCLUDE_DIRS})
|
||||
|
||||
set(HEIMDALL_FRONTEND_SOURCE_FILES
|
||||
source/aboutform.cpp
|
||||
source/Alerts.cpp
|
||||
source/FirmwareInfo.cpp
|
||||
source/main.cpp
|
||||
source/mainwindow.cpp
|
||||
source/PackageData.cpp
|
||||
source/Packaging.cpp)
|
||||
|
||||
qt5_wrap_ui(HEIMDALL_FRONTEND_FORMS
|
||||
mainwindow.ui
|
||||
aboutform.ui)
|
||||
|
||||
qt5_add_resources(HEIMDALL_FRONTEND_RESOURCES
|
||||
mainwindow.qrc)
|
||||
|
||||
add_executable(heimdall-frontend WIN32
|
||||
MACOSX_BUNDLE
|
||||
${HEIMDALL_FRONTEND_SOURCE_FILES}
|
||||
${HEIMDALL_FRONTEND_FORMS}
|
||||
${HEIMDALL_FRONTEND_RESOURCES})
|
||||
|
||||
include(LargeFiles)
|
||||
use_large_files(heimdall-frontend YES)
|
||||
|
||||
set_property(TARGET heimdall-frontend
|
||||
APPEND PROPERTY COMPILE_DEFINITIONS "QT_LARGEFILE_SUPPORT")
|
||||
|
||||
target_link_libraries(heimdall-frontend pit)
|
||||
target_link_libraries(heimdall-frontend Qt5::Widgets)
|
||||
target_link_libraries(heimdall-frontend z)
|
||||
install (TARGETS heimdall-frontend
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
455
heimdall-frontend/aboutform.ui
Normal file
455
heimdall-frontend/aboutform.ui
Normal file
|
@ -0,0 +1,455 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutForm</class>
|
||||
<widget class="QWidget" name="AboutForm">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>581</width>
|
||||
<height>491</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>581</width>
|
||||
<height>491</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>581</width>
|
||||
<height>491</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About Heimdall Frontend</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="okPushButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>250</x>
|
||||
<y>460</y>
|
||||
<width>75</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>561</width>
|
||||
<height>441</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-701</y>
|
||||
<width>542</width>
|
||||
<height>1140</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="versionCopyrightLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Heimdall Frontend</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version 1.4.2</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2010-2017 Benjamin Dobell, Glass Echidna</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Heimdall (command line)</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">%HEIMDALL-VERSION%Copyright © 2010-2017 Benjamin Dobell, Glass Echidna</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">If you appreciate this software and you would like to support future development please consider donating:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.glassechidna.com.au/donate/"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.glassechidna.com.au/donate/</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Glass Echidna Homepage:</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.glassechidna.com.au/"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.glassechidna.com.au/</span></a></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;"></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Heimdall Homepage:</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.glassechidna.com.au/products/heimdall/"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.glassechidna.com.au/products/heimdall/</span></a></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;"></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Heimdall and Heimdall Frontend are licensed under the following license:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Heimdall Frontend's user interface is powered by the Qt Framework:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Copyright © 2008-2011 Nokia Corporation</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Qt is licensed under the </span><a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">Lesser General Public License v2.1.</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Heimdall Frontend utilises zlib for package compression:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">zlib is licensed under the following license:</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Copyright © 1995-2010 Jean-loup Gailly and Mark Adler</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">3. This notice may not be removed or altered from any source distribution.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Heimdall (command line) utilises libusbx for all USB communication:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">libusbx is licensed under the </span><a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Lesser General Public License v2.1.</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>okPushButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>AboutForm</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>287</x>
|
||||
<y>470</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>290</x>
|
||||
<y>245</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
4
heimdall-frontend/mainwindow.qrc
Normal file
4
heimdall-frontend/mainwindow.qrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
<RCC>
|
||||
<qresource prefix="MainWindow">
|
||||
</qresource>
|
||||
</RCC>
|
1994
heimdall-frontend/mainwindow.ui
Normal file
1994
heimdall-frontend/mainwindow.ui
Normal file
File diff suppressed because it is too large
Load diff
45
heimdall-frontend/source/Alerts.cpp
Normal file
45
heimdall-frontend/source/Alerts.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Qt
|
||||
#include <QMessageBox>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "Alerts.h"
|
||||
|
||||
using namespace HeimdallFrontend;
|
||||
|
||||
void Alerts::DisplayError(const QString& errorMessage)
|
||||
{
|
||||
QMessageBox messageBox;
|
||||
messageBox.setModal(true);
|
||||
messageBox.setText(errorMessage);
|
||||
messageBox.setIcon(QMessageBox::Critical);
|
||||
messageBox.exec();
|
||||
}
|
||||
|
||||
void Alerts::DisplayWarning(const QString& warningMessage)
|
||||
{
|
||||
QMessageBox messageBox;
|
||||
messageBox.setModal(true);
|
||||
messageBox.setText(warningMessage);
|
||||
messageBox.setIcon(QMessageBox::Warning);
|
||||
messageBox.exec();
|
||||
}
|
38
heimdall-frontend/source/Alerts.h
Normal file
38
heimdall-frontend/source/Alerts.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ALERTS_H
|
||||
#define ALERTS_H
|
||||
|
||||
// Qt
|
||||
#include <QString>
|
||||
|
||||
namespace HeimdallFrontend
|
||||
{
|
||||
class Alerts
|
||||
{
|
||||
public:
|
||||
|
||||
static void DisplayError(const QString& errorMessage);
|
||||
static void DisplayWarning(const QString& warningMessage);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
783
heimdall-frontend/source/FirmwareInfo.cpp
Normal file
783
heimdall-frontend/source/FirmwareInfo.cpp
Normal file
|
@ -0,0 +1,783 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Qt
|
||||
#include "QRegExp"
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "Alerts.h"
|
||||
#include "FirmwareInfo.h"
|
||||
#include "Packaging.h"
|
||||
|
||||
using namespace HeimdallFrontend;
|
||||
|
||||
DeviceInfo::DeviceInfo()
|
||||
{
|
||||
}
|
||||
|
||||
DeviceInfo::DeviceInfo(const QString& manufacturer, const QString& product, const QString& name)
|
||||
{
|
||||
this->manufacturer = manufacturer;
|
||||
this->product = product;
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
bool DeviceInfo::ParseXml(QXmlStreamReader& xml)
|
||||
{
|
||||
bool foundManufacturer = false;
|
||||
bool foundProduct = false;
|
||||
bool foundName = false;
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
QXmlStreamReader::TokenType nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "manufacturer")
|
||||
{
|
||||
if (foundManufacturer)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <manufacturer> elements in <device>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundManufacturer = true;
|
||||
|
||||
manufacturer = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "product")
|
||||
{
|
||||
if (foundProduct)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <product> elements in <device>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundProduct = true;
|
||||
|
||||
product = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "name")
|
||||
{
|
||||
if (foundName)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <name> elements in <device>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundName = true;
|
||||
|
||||
name = xml.readElementText();
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <device>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "device")
|
||||
{
|
||||
if (foundManufacturer && foundProduct && foundName)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError("Required elements are missing from <device>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <device>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
void DeviceInfo::WriteXml(QXmlStreamWriter& xml) const
|
||||
{
|
||||
xml.writeStartElement("device");
|
||||
|
||||
xml.writeStartElement("manufacturer");
|
||||
xml.writeCharacters(manufacturer);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("product");
|
||||
xml.writeCharacters(product);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("name");
|
||||
xml.writeCharacters(name);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
PlatformInfo::PlatformInfo()
|
||||
{
|
||||
}
|
||||
|
||||
void PlatformInfo::Clear(void)
|
||||
{
|
||||
name.clear();
|
||||
version.clear();
|
||||
}
|
||||
|
||||
bool PlatformInfo::IsCleared(void) const
|
||||
{
|
||||
return (name.isEmpty() && version.isEmpty());
|
||||
}
|
||||
|
||||
bool PlatformInfo::ParseXml(QXmlStreamReader& xml)
|
||||
{
|
||||
Clear();
|
||||
|
||||
bool foundName = false;
|
||||
bool foundVersion = false;
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
QXmlStreamReader::TokenType nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "name")
|
||||
{
|
||||
if (foundName)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <name> elements in <platform>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundName = true;
|
||||
|
||||
name = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "version")
|
||||
{
|
||||
if (foundVersion)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <version> elements in <platform>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundVersion = true;
|
||||
|
||||
version = xml.readElementText();
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <platform>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "platform")
|
||||
{
|
||||
if (foundName && foundVersion)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError("Required elements are missing from <platform>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <platform>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
void PlatformInfo::WriteXml(QXmlStreamWriter& xml) const
|
||||
{
|
||||
xml.writeStartElement("platform");
|
||||
|
||||
xml.writeStartElement("name");
|
||||
xml.writeCharacters(name);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("version");
|
||||
xml.writeCharacters(version);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
FileInfo::FileInfo()
|
||||
{
|
||||
}
|
||||
|
||||
FileInfo::FileInfo(unsigned int partitionId, const QString& filename)
|
||||
{
|
||||
this->partitionId = partitionId;
|
||||
this->filename = filename;
|
||||
}
|
||||
|
||||
bool FileInfo::ParseXml(QXmlStreamReader& xml)
|
||||
{
|
||||
bool foundId = false;
|
||||
bool foundFilename = false;
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
QXmlStreamReader::TokenType nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "id")
|
||||
{
|
||||
if (foundId)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <id> elements in <file>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundId = true;
|
||||
|
||||
partitionId = xml.readElementText().toInt();
|
||||
}
|
||||
else if (xml.name() == "filename")
|
||||
{
|
||||
if (foundFilename)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <filename> elements in <file>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundFilename = true;
|
||||
|
||||
filename = xml.readElementText();
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <file>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "file")
|
||||
{
|
||||
if (foundId && foundFilename)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError("Required elements are missing from <file>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <file>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
void FileInfo::WriteXml(QXmlStreamWriter& xml, const QString& filename) const
|
||||
{
|
||||
xml.writeStartElement("file");
|
||||
|
||||
xml.writeStartElement("id");
|
||||
xml.writeCharacters(QString::number(partitionId));
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("filename");
|
||||
xml.writeCharacters(filename);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
FirmwareInfo::FirmwareInfo()
|
||||
{
|
||||
repartition = false;
|
||||
noReboot = false;
|
||||
}
|
||||
|
||||
void FirmwareInfo::Clear(void)
|
||||
{
|
||||
name = "";
|
||||
version = "";
|
||||
platformInfo.Clear();
|
||||
|
||||
developers.clear();
|
||||
url.clear();
|
||||
donateUrl.clear();
|
||||
|
||||
deviceInfos.clear();
|
||||
|
||||
pitFilename.clear();
|
||||
repartition = false;
|
||||
|
||||
noReboot = false;
|
||||
|
||||
fileInfos.clear();
|
||||
}
|
||||
|
||||
bool FirmwareInfo::IsCleared(void) const
|
||||
{
|
||||
return (name.isEmpty() && version.isEmpty() && platformInfo.IsCleared() && developers.isEmpty() && url.isEmpty() && url.isEmpty() && donateUrl.isEmpty()
|
||||
&& deviceInfos.isEmpty() && pitFilename.isEmpty() && !repartition && !noReboot && fileInfos.isEmpty());
|
||||
}
|
||||
|
||||
bool FirmwareInfo::ParseXml(QXmlStreamReader& xml)
|
||||
{
|
||||
Clear();
|
||||
|
||||
bool foundName = false;
|
||||
bool foundVersion = false;
|
||||
bool foundPlatform = false;
|
||||
bool foundDevelopers = false;
|
||||
bool foundUrl = false;
|
||||
bool foundDonateUrl = false;
|
||||
bool foundDevices = false;
|
||||
bool foundPit = false;
|
||||
bool foundRepartition = false;
|
||||
bool foundNoReboot = false;
|
||||
bool foundFiles = false;
|
||||
|
||||
if (!xml.readNextStartElement())
|
||||
{
|
||||
Alerts::DisplayError("Failed to find <firmware> element.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (xml.name() != "firmware")
|
||||
{
|
||||
Alerts::DisplayError(QString("Expected <firmware> element but found <%1>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
|
||||
QString formatVersionString;
|
||||
formatVersionString += xml.attributes().value("version");
|
||||
|
||||
if (formatVersionString.isEmpty())
|
||||
{
|
||||
Alerts::DisplayError("<firmware> is missing the version attribute.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool parsedVersion = false;
|
||||
int formatVersion = formatVersionString.toInt(&parsedVersion);
|
||||
|
||||
if (!parsedVersion)
|
||||
{
|
||||
Alerts::DisplayError("<firmware> contains a malformed version.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (formatVersion > kVersion)
|
||||
{
|
||||
Alerts::DisplayError("Package is for a newer version of Heimdall Frontend.\nPlease download the latest version of Heimdall Frontend.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
QXmlStreamReader::TokenType nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "name")
|
||||
{
|
||||
if (foundName)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <name> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundName = true;
|
||||
name = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "version")
|
||||
{
|
||||
if (foundVersion)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <version> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundVersion = true;
|
||||
version = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "platform")
|
||||
{
|
||||
if (foundPlatform)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <platform> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundPlatform = true;
|
||||
|
||||
if (!platformInfo.ParseXml(xml))
|
||||
return (false);
|
||||
}
|
||||
else if (xml.name() == "developers")
|
||||
{
|
||||
if (foundDevelopers)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <developers> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundDevelopers = true;
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "name")
|
||||
{
|
||||
developers.append(xml.readElementText());
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <developers>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "developers")
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <developers>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (xml.name() == "url")
|
||||
{
|
||||
if (foundUrl)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <url> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundUrl = true;
|
||||
|
||||
url = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "donateurl")
|
||||
{
|
||||
if (foundDonateUrl)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <donateurl> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundDonateUrl = true;
|
||||
|
||||
donateUrl = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "devices")
|
||||
{
|
||||
if (foundDevices)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <devices> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundDevices = true;
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "device")
|
||||
{
|
||||
DeviceInfo deviceInfo;
|
||||
|
||||
if (!deviceInfo.ParseXml(xml))
|
||||
return (false);
|
||||
|
||||
deviceInfos.append(deviceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <devices>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "devices")
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <devices>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (xml.name() == "pit")
|
||||
{
|
||||
if (foundPit)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <pit> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundPit = true;
|
||||
|
||||
pitFilename = xml.readElementText();
|
||||
}
|
||||
else if (xml.name() == "repartition")
|
||||
{
|
||||
if (foundRepartition)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <repartition> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundRepartition = true;
|
||||
|
||||
repartition = (xml.readElementText().toInt() != 0);
|
||||
}
|
||||
else if (xml.name() == "noreboot")
|
||||
{
|
||||
if (foundNoReboot)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <noreboot> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundNoReboot = true;
|
||||
|
||||
noReboot = (xml.readElementText().toInt() != 0);
|
||||
}
|
||||
else if (xml.name() == "files")
|
||||
{
|
||||
if (foundFiles)
|
||||
{
|
||||
Alerts::DisplayError("Found multiple <files> elements in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
foundFiles = true;
|
||||
|
||||
while (!xml.atEnd())
|
||||
{
|
||||
nextToken = xml.readNext();
|
||||
|
||||
if (nextToken == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (xml.name() == "file")
|
||||
{
|
||||
FileInfo fileInfo;
|
||||
|
||||
if (!fileInfo.ParseXml(xml))
|
||||
return (false);
|
||||
|
||||
fileInfos.append(fileInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <files>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "files")
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <devices>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Alerts::DisplayError(QString("<%1> is not a valid child of <firmware>.").arg(xml.name().toString()));
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else if (nextToken == QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xml.name() == "firmware")
|
||||
{
|
||||
if (!(foundName && foundVersion && foundPlatform && foundDevelopers && foundDevices && foundPit && foundRepartition && foundNoReboot && foundFiles))
|
||||
{
|
||||
Alerts::DisplayError("Required elements are missing from <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace()))
|
||||
{
|
||||
Alerts::DisplayError("Unexpected token found in <firmware>.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read whitespaces at the end of the file (if there are any)
|
||||
xml.readNext();
|
||||
|
||||
if (!xml.atEnd())
|
||||
{
|
||||
Alerts::DisplayError("Found data after </firmware>.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
void FirmwareInfo::WriteXml(QXmlStreamWriter& xml) const
|
||||
{
|
||||
xml.writeStartDocument();
|
||||
xml.writeStartElement("firmware");
|
||||
xml.writeAttribute("version", QString::number(FirmwareInfo::kVersion));
|
||||
|
||||
xml.writeStartElement("name");
|
||||
xml.writeCharacters(name);
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("version");
|
||||
xml.writeCharacters(version);
|
||||
xml.writeEndElement();
|
||||
|
||||
platformInfo.WriteXml(xml);
|
||||
|
||||
xml.writeStartElement("developers");
|
||||
|
||||
for (int i = 0; i < developers.length(); i++)
|
||||
{
|
||||
xml.writeStartElement("name");
|
||||
xml.writeCharacters(developers[i]);
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
xml.writeEndElement();
|
||||
|
||||
if (!url.isEmpty())
|
||||
{
|
||||
xml.writeStartElement("url");
|
||||
xml.writeCharacters(url);
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
if (!donateUrl.isEmpty())
|
||||
{
|
||||
xml.writeStartElement("donateurl");
|
||||
xml.writeCharacters(donateUrl);
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
xml.writeStartElement("devices");
|
||||
|
||||
for (int i = 0; i < deviceInfos.length(); i++)
|
||||
deviceInfos[i].WriteXml(xml);
|
||||
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("pit");
|
||||
|
||||
int lastSlash = pitFilename.lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = pitFilename.lastIndexOf('\\');
|
||||
|
||||
xml.writeCharacters(pitFilename.mid(lastSlash + 1));
|
||||
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("repartition");
|
||||
xml.writeCharacters((repartition) ? "1" : "0");
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("noreboot");
|
||||
xml.writeCharacters((noReboot) ? "1" : "0");
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("files");
|
||||
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
fileInfos[i].WriteXml(xml, Packaging::ClashlessFilename(fileInfos, i));
|
||||
}
|
||||
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeEndElement();
|
||||
xml.writeEndDocument();
|
||||
}
|
302
heimdall-frontend/source/FirmwareInfo.h
Normal file
302
heimdall-frontend/source/FirmwareInfo.h
Normal file
|
@ -0,0 +1,302 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef FIRMWAREINFO_H
|
||||
#define FIRMWAREINFO_H
|
||||
|
||||
// Qt
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
namespace HeimdallFrontend
|
||||
{
|
||||
class DeviceInfo
|
||||
{
|
||||
private:
|
||||
|
||||
QString manufacturer;
|
||||
QString product;
|
||||
QString name;
|
||||
|
||||
public:
|
||||
|
||||
DeviceInfo();
|
||||
DeviceInfo(const QString& manufacturer, const QString& product, const QString& name);
|
||||
|
||||
bool ParseXml(QXmlStreamReader& xml);
|
||||
void WriteXml(QXmlStreamWriter& xml) const;
|
||||
|
||||
const QString& GetManufacturer(void) const
|
||||
{
|
||||
return (manufacturer);
|
||||
}
|
||||
|
||||
void SetManufacturer(const QString& manufacturer)
|
||||
{
|
||||
this->manufacturer = manufacturer;
|
||||
}
|
||||
|
||||
const QString& GetProduct(void) const
|
||||
{
|
||||
return (product);
|
||||
}
|
||||
|
||||
void SetProduct(const QString& product)
|
||||
{
|
||||
this->product = product;
|
||||
}
|
||||
|
||||
const QString& GetName(void) const
|
||||
{
|
||||
return (name);
|
||||
}
|
||||
|
||||
void SetName(const QString& name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
};
|
||||
|
||||
class PlatformInfo
|
||||
{
|
||||
private:
|
||||
|
||||
QString name;
|
||||
QString version;
|
||||
|
||||
public:
|
||||
|
||||
PlatformInfo();
|
||||
|
||||
void Clear(void);
|
||||
bool IsCleared(void) const;
|
||||
|
||||
bool ParseXml(QXmlStreamReader& xml);
|
||||
void WriteXml(QXmlStreamWriter& xml) const;
|
||||
|
||||
const QString& GetName(void) const
|
||||
{
|
||||
return (name);
|
||||
}
|
||||
|
||||
void SetName(const QString& name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
const QString& GetVersion(void) const
|
||||
{
|
||||
return (version);
|
||||
}
|
||||
|
||||
void SetVersion(const QString& version)
|
||||
{
|
||||
this->version = version;
|
||||
}
|
||||
};
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int partitionId;
|
||||
QString filename;
|
||||
|
||||
public:
|
||||
|
||||
FileInfo();
|
||||
FileInfo(unsigned int partitionId, const QString& filename);
|
||||
|
||||
bool ParseXml(QXmlStreamReader& xml);
|
||||
void WriteXml(QXmlStreamWriter& xml, const QString& filename) const;
|
||||
|
||||
unsigned int GetPartitionId(void) const
|
||||
{
|
||||
return (partitionId);
|
||||
}
|
||||
|
||||
void SetPartitionId(unsigned int partitionId)
|
||||
{
|
||||
this->partitionId = partitionId;
|
||||
}
|
||||
|
||||
const QString& GetFilename(void) const
|
||||
{
|
||||
return (filename);
|
||||
}
|
||||
|
||||
void SetFilename(const QString& filename)
|
||||
{
|
||||
this->filename = filename;
|
||||
}
|
||||
};
|
||||
|
||||
class FirmwareInfo
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kVersion = 1
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
QString name;
|
||||
QString version;
|
||||
PlatformInfo platformInfo;
|
||||
|
||||
QList<QString> developers;
|
||||
QString url;
|
||||
QString donateUrl;
|
||||
|
||||
QList<DeviceInfo> deviceInfos;
|
||||
|
||||
QString pitFilename;
|
||||
bool repartition;
|
||||
|
||||
bool noReboot;
|
||||
|
||||
QList<FileInfo> fileInfos;
|
||||
|
||||
public:
|
||||
|
||||
FirmwareInfo();
|
||||
|
||||
void Clear(void);
|
||||
bool IsCleared(void) const;
|
||||
|
||||
bool ParseXml(QXmlStreamReader& xml);
|
||||
void WriteXml(QXmlStreamWriter& xml) const;
|
||||
|
||||
const QString& GetName(void) const
|
||||
{
|
||||
return (name);
|
||||
}
|
||||
|
||||
void SetName(const QString& name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
const QString& GetVersion(void) const
|
||||
{
|
||||
return (version);
|
||||
}
|
||||
|
||||
void SetVersion(const QString& version)
|
||||
{
|
||||
this->version = version;
|
||||
}
|
||||
|
||||
const PlatformInfo& GetPlatformInfo(void) const
|
||||
{
|
||||
return (platformInfo);
|
||||
}
|
||||
|
||||
PlatformInfo& GetPlatformInfo(void)
|
||||
{
|
||||
return (platformInfo);
|
||||
}
|
||||
|
||||
const QList<QString>& GetDevelopers(void) const
|
||||
{
|
||||
return (developers);
|
||||
}
|
||||
|
||||
QList<QString>& GetDevelopers(void)
|
||||
{
|
||||
return (developers);
|
||||
}
|
||||
|
||||
const QString& GetUrl(void) const
|
||||
{
|
||||
return (url);
|
||||
}
|
||||
|
||||
void SetUrl(const QString& url)
|
||||
{
|
||||
this->url = url;
|
||||
}
|
||||
|
||||
const QString& GetDonateUrl(void) const
|
||||
{
|
||||
return (donateUrl);
|
||||
}
|
||||
|
||||
void SetDonateUrl(const QString& donateUrl)
|
||||
{
|
||||
this->donateUrl = donateUrl;
|
||||
}
|
||||
|
||||
const QList<DeviceInfo>& GetDeviceInfos(void) const
|
||||
{
|
||||
return (deviceInfos);
|
||||
}
|
||||
|
||||
QList<DeviceInfo>& GetDeviceInfos(void)
|
||||
{
|
||||
return (deviceInfos);
|
||||
}
|
||||
|
||||
const QString& GetPitFilename(void) const
|
||||
{
|
||||
return (pitFilename);
|
||||
}
|
||||
|
||||
void SetPitFilename(const QString& pitFilename)
|
||||
{
|
||||
this->pitFilename = pitFilename;
|
||||
}
|
||||
|
||||
bool GetRepartition(void) const
|
||||
{
|
||||
return (repartition);
|
||||
}
|
||||
|
||||
void SetRepartition(bool repartition)
|
||||
{
|
||||
this->repartition = repartition;
|
||||
}
|
||||
|
||||
bool GetNoReboot(void) const
|
||||
{
|
||||
return (noReboot);
|
||||
}
|
||||
|
||||
void SetNoReboot(bool noReboot)
|
||||
{
|
||||
this->noReboot = noReboot;
|
||||
}
|
||||
|
||||
const QList<FileInfo>& GetFileInfos(void) const
|
||||
{
|
||||
return (fileInfos);
|
||||
}
|
||||
|
||||
QList<FileInfo>& GetFileInfos(void)
|
||||
{
|
||||
return (fileInfos);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
66
heimdall-frontend/source/PackageData.cpp
Normal file
66
heimdall-frontend/source/PackageData.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "Alerts.h"
|
||||
#include "PackageData.h"
|
||||
|
||||
using namespace HeimdallFrontend;
|
||||
|
||||
PackageData::PackageData()
|
||||
{
|
||||
}
|
||||
|
||||
PackageData::~PackageData()
|
||||
{
|
||||
for (int i = 0; i < files.length(); i++)
|
||||
delete files[i];
|
||||
}
|
||||
|
||||
void PackageData::Clear(void)
|
||||
{
|
||||
firmwareInfo.Clear();
|
||||
|
||||
for (int i = 0; i < files.length(); i++)
|
||||
delete files[i];
|
||||
|
||||
files.clear();
|
||||
}
|
||||
|
||||
bool PackageData::ReadFirmwareInfo(QFile *file)
|
||||
{
|
||||
if (!file->open(QFile::ReadOnly))
|
||||
{
|
||||
Alerts::DisplayError(QString("Failed to open file: \1%s").arg(file->fileName()));
|
||||
return (false);
|
||||
}
|
||||
|
||||
QXmlStreamReader xml(file);
|
||||
bool success = firmwareInfo.ParseXml(xml);
|
||||
|
||||
file->close();
|
||||
|
||||
return (success);
|
||||
}
|
||||
|
||||
bool PackageData::IsCleared(void) const
|
||||
{
|
||||
return (firmwareInfo.IsCleared() && files.isEmpty());
|
||||
}
|
77
heimdall-frontend/source/PackageData.h
Normal file
77
heimdall-frontend/source/PackageData.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef PACKAGEDATA_H
|
||||
#define PACKAGEDATA_H
|
||||
|
||||
// Qt
|
||||
#include <QTemporaryFile>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "FirmwareInfo.h"
|
||||
|
||||
namespace HeimdallFrontend
|
||||
{
|
||||
class PackageData
|
||||
{
|
||||
private:
|
||||
|
||||
FirmwareInfo firmwareInfo;
|
||||
QList<QTemporaryFile *> files;
|
||||
|
||||
public:
|
||||
|
||||
PackageData();
|
||||
~PackageData();
|
||||
|
||||
void Clear(void);
|
||||
bool ReadFirmwareInfo(QFile *file);
|
||||
|
||||
bool IsCleared(void) const;
|
||||
|
||||
const FirmwareInfo& GetFirmwareInfo(void) const
|
||||
{
|
||||
return (firmwareInfo);
|
||||
}
|
||||
|
||||
FirmwareInfo& GetFirmwareInfo(void)
|
||||
{
|
||||
return (firmwareInfo);
|
||||
}
|
||||
|
||||
const QList<QTemporaryFile *>& GetFiles(void) const
|
||||
{
|
||||
return (files);
|
||||
}
|
||||
|
||||
QList<QTemporaryFile *>& GetFiles(void)
|
||||
{
|
||||
return (files);
|
||||
}
|
||||
|
||||
// Simply clears the files list, it does delete/close any files.
|
||||
void RemoveAllFiles(void)
|
||||
{
|
||||
files.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
934
heimdall-frontend/source/Packaging.cpp
Normal file
934
heimdall-frontend/source/Packaging.cpp
Normal file
|
@ -0,0 +1,934 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <stdio.h>
|
||||
|
||||
// zlib
|
||||
#include "zlib.h"
|
||||
|
||||
// Qt
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QProgressDialog>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "Alerts.h"
|
||||
#include "Packaging.h"
|
||||
|
||||
using namespace HeimdallFrontend;
|
||||
|
||||
const qint64 Packaging::kMaxFileSize = 8589934592ll;
|
||||
const char *Packaging::ustarMagic = "ustar";
|
||||
|
||||
bool Packaging::ExtractTar(QTemporaryFile& tarFile, PackageData *packageData)
|
||||
{
|
||||
TarHeader tarHeader;
|
||||
|
||||
if (!tarFile.open())
|
||||
{
|
||||
Alerts::DisplayError(QString("Error opening temporary TAR archive:\n%1").arg(tarFile.fileName()));
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool previousEmpty = false;
|
||||
|
||||
QProgressDialog progressDialog("Extracting files...", "Cancel", 0, tarFile.size());
|
||||
progressDialog.setWindowModality(Qt::ApplicationModal);
|
||||
progressDialog.setWindowTitle("Heimdall Frontend");
|
||||
|
||||
while (!tarFile.atEnd())
|
||||
{
|
||||
qint64 dataRead = tarFile.read(tarHeader.buffer, TarHeader::kBlockLength);
|
||||
|
||||
if (dataRead != TarHeader::kBlockLength)
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Package's TAR archive is malformed.");
|
||||
|
||||
tarFile.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
progressDialog.setValue(tarFile.pos());
|
||||
|
||||
if (progressDialog.wasCanceled())
|
||||
{
|
||||
tarFile.close();
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
//bool ustarFormat = strcmp(tarHeader.fields.magic, ustarMagic) == 0;
|
||||
bool empty = true;
|
||||
|
||||
for (int i = 0; i < TarHeader::kBlockLength; i++)
|
||||
{
|
||||
if (tarHeader.buffer[i] != 0)
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty)
|
||||
{
|
||||
if (previousEmpty)
|
||||
{
|
||||
// Two empty blocks in a row means we've reached the end of the archive.
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int checksum = 0;
|
||||
|
||||
for (char *bufferIndex = tarHeader.buffer; bufferIndex < tarHeader.fields.checksum; bufferIndex++)
|
||||
checksum += static_cast<unsigned char>(*bufferIndex);
|
||||
|
||||
checksum += 8 * ' ';
|
||||
checksum += static_cast<unsigned char>(tarHeader.fields.typeFlag);
|
||||
|
||||
// Both the TAR and USTAR formats have terrible documentation, it's not clear if the following code is required.
|
||||
/*if (ustarFormat)
|
||||
{
|
||||
for (char *bufferIndex = tarHeader.fields.linkName; bufferIndex < tarHeader.fields.prefix + 155; bufferIndex++)
|
||||
checksum += static_cast<unsigned char>(*bufferIndex);
|
||||
}*/
|
||||
|
||||
bool parsed = false;
|
||||
|
||||
// The size field is not always null terminated, so we must create a copy and null terminate it for parsing.
|
||||
char fileSizeString[13];
|
||||
memcpy(fileSizeString, tarHeader.fields.size, 12);
|
||||
fileSizeString[12] = '\0';
|
||||
|
||||
qulonglong fileSize = QString(fileSizeString).toULongLong(&parsed, 8);
|
||||
|
||||
if (!parsed)
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Tar header contained an invalid file size.");
|
||||
|
||||
tarFile.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (fileSize > 0 && tarHeader.fields.typeFlag == '0')
|
||||
{
|
||||
// We're working with a file.
|
||||
QString filename = QString::fromUtf8(tarHeader.fields.name);
|
||||
|
||||
QTemporaryFile *outputFile = new QTemporaryFile("XXXXXX-" + filename);
|
||||
packageData->GetFiles().append(outputFile);
|
||||
|
||||
if (!outputFile->open())
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError(QString("Failed to open output file: \n%1").arg(outputFile->fileName()));
|
||||
|
||||
tarFile.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
qulonglong dataRemaining = fileSize;
|
||||
char readBuffer[TarHeader::kBlockReadCount * TarHeader::kBlockLength];
|
||||
|
||||
// Copy the file contents from tarFile to outputFile
|
||||
while (dataRemaining > 0)
|
||||
{
|
||||
qint64 fileDataToRead = (dataRemaining < TarHeader::kBlockReadCount * TarHeader::kBlockLength)
|
||||
? dataRemaining : TarHeader::kBlockReadCount * TarHeader::kBlockLength;
|
||||
|
||||
qint64 dataRead = tarFile.read(readBuffer, fileDataToRead + (TarHeader::kBlockLength - fileDataToRead % TarHeader::kBlockLength) % TarHeader::kBlockLength);
|
||||
|
||||
if (dataRead < fileDataToRead || dataRead % TarHeader::kBlockLength != 0)
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Unexpected read error whilst extracting package files.");
|
||||
|
||||
tarFile.close();
|
||||
outputFile->close();
|
||||
|
||||
remove(outputFile->fileName().toStdString().c_str());
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
outputFile->write(readBuffer, fileDataToRead);
|
||||
|
||||
dataRemaining -= fileDataToRead;
|
||||
|
||||
progressDialog.setValue(tarFile.pos());
|
||||
|
||||
if (progressDialog.wasCanceled())
|
||||
{
|
||||
tarFile.close();
|
||||
outputFile->close();
|
||||
|
||||
remove(outputFile->fileName().toStdString().c_str());
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
outputFile->close();
|
||||
}
|
||||
else
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Heimdall packages shouldn't contain links or directories.");
|
||||
|
||||
tarFile.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
previousEmpty = empty;
|
||||
}
|
||||
|
||||
progressDialog.close();
|
||||
tarFile.close();
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool Packaging::WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, const QString& entryFilename)
|
||||
{
|
||||
TarHeader tarHeader;
|
||||
memset(tarHeader.buffer, 0, TarHeader::kBlockLength);
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
Alerts::DisplayError(QString("Failed to open file: \n%1").arg(file.fileName()));
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (file.size() > Packaging::kMaxFileSize)
|
||||
{
|
||||
Alerts::DisplayError(QString("File is too large to be packaged:\n%1").arg(file.fileName()));
|
||||
return (false);
|
||||
}
|
||||
|
||||
QFileInfo qtFileInfo(file);
|
||||
QByteArray utfFilename;
|
||||
|
||||
utfFilename = entryFilename.toUtf8();
|
||||
|
||||
if (utfFilename.length() > 100)
|
||||
{
|
||||
Alerts::DisplayError(QString("File name is too long:\n%1").arg(qtFileInfo.fileName()));
|
||||
return (false);
|
||||
}
|
||||
|
||||
strcpy(tarHeader.fields.name, utfFilename.constData());
|
||||
|
||||
unsigned int mode = 0;
|
||||
|
||||
QFile::Permissions permissions = file.permissions();
|
||||
|
||||
// Other
|
||||
if (permissions.testFlag(QFile::ExeOther))
|
||||
mode |= TarHeader::kModeOtherExecute;
|
||||
if (permissions.testFlag(QFile::WriteOther))
|
||||
mode |= TarHeader::kModeOtherWrite;
|
||||
if (permissions.testFlag(QFile::ReadOther))
|
||||
mode |= TarHeader::kModeOtherRead;
|
||||
|
||||
// Group
|
||||
if (permissions.testFlag(QFile::ExeGroup))
|
||||
mode |= TarHeader::kModeGroupExecute;
|
||||
if (permissions.testFlag(QFile::WriteGroup))
|
||||
mode |= TarHeader::kModeGroupWrite;
|
||||
if (permissions.testFlag(QFile::ReadGroup))
|
||||
mode |= TarHeader::kModeGroupRead;
|
||||
|
||||
// Owner
|
||||
if (permissions.testFlag(QFile::ExeOwner))
|
||||
mode |= TarHeader::kModeOwnerExecute;
|
||||
if (permissions.testFlag(QFile::WriteOwner))
|
||||
mode |= TarHeader::kModeOwnerWrite;
|
||||
if (permissions.testFlag(QFile::ReadOwner))
|
||||
mode |= TarHeader::kModeOwnerRead;
|
||||
|
||||
sprintf(tarHeader.fields.mode, "%07o", mode);
|
||||
|
||||
// Owner id
|
||||
uint id = qtFileInfo.ownerId();
|
||||
|
||||
if (id < 2097151)
|
||||
sprintf(tarHeader.fields.userId, "%07o", id);
|
||||
else
|
||||
sprintf(tarHeader.fields.userId, "%07o", 0);
|
||||
|
||||
// Group id
|
||||
id = qtFileInfo.groupId();
|
||||
|
||||
if (id < 2097151)
|
||||
sprintf(tarHeader.fields.groupId, "%07o", id);
|
||||
else
|
||||
sprintf(tarHeader.fields.groupId, "%07o", 0);
|
||||
|
||||
// Note: We don't support base-256 encoding. Support could be added later.
|
||||
sprintf(tarHeader.fields.size, "%011llo", file.size());
|
||||
sprintf(tarHeader.fields.modifiedTime, "%u", qtFileInfo.lastModified().toTime_t());
|
||||
|
||||
// Regular File
|
||||
tarHeader.fields.typeFlag = '0';
|
||||
|
||||
// Calculate checksum
|
||||
int checksum = 0;
|
||||
memset(tarHeader.fields.checksum, ' ', 8);
|
||||
|
||||
for (int i = 0; i < TarHeader::kTarHeaderLength; i++)
|
||||
checksum += static_cast<unsigned char>(tarHeader.buffer[i]);
|
||||
|
||||
sprintf(tarHeader.fields.checksum, "%07o", checksum);
|
||||
|
||||
// Write the header to the TAR file.
|
||||
tarFile->write(tarHeader.buffer, TarHeader::kBlockLength);
|
||||
|
||||
char buffer[TarHeader::kBlockWriteCount * TarHeader::kBlockLength];
|
||||
qint64 offset = 0;
|
||||
|
||||
while (offset < file.size())
|
||||
{
|
||||
qint64 dataRead = file.read(buffer, TarHeader::kBlockWriteCount * TarHeader::kBlockLength);
|
||||
|
||||
if (tarFile->write(buffer, dataRead) != dataRead)
|
||||
{
|
||||
Alerts::DisplayError("Failed to write data to the temporary TAR file.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (dataRead % TarHeader::kBlockLength != 0)
|
||||
{
|
||||
int remainingBlockLength = TarHeader::kBlockLength - dataRead % TarHeader::kBlockLength;
|
||||
memset(buffer, 0, remainingBlockLength);
|
||||
|
||||
if (tarFile->write(buffer, remainingBlockLength) != remainingBlockLength)
|
||||
{
|
||||
Alerts::DisplayError("Failed to write data to the temporary TAR file.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
offset += dataRead;
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarFile)
|
||||
{
|
||||
const QList<FileInfo>& fileInfos = firmwareInfo.GetFileInfos();
|
||||
|
||||
QProgressDialog progressDialog("Packaging files...", "Cancel", 0, fileInfos.length() + 2);
|
||||
progressDialog.setWindowModality(Qt::ApplicationModal);
|
||||
progressDialog.setWindowTitle("Heimdall Frontend");
|
||||
|
||||
QTemporaryFile firmwareXmlFile("XXXXXX-firmware.xml");
|
||||
|
||||
if (!firmwareXmlFile.open())
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError(QString("Failed to create temporary file: \n%1").arg(firmwareXmlFile.fileName()));
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
QXmlStreamWriter xml(&firmwareXmlFile);
|
||||
firmwareInfo.WriteXml(xml);
|
||||
firmwareXmlFile.close();
|
||||
|
||||
if (!tarFile->open())
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError(QString("Failed to open file: \n%1").arg(tarFile->fileName()));
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
// If the file was already compressed we don't compress it again.
|
||||
bool skip = false;
|
||||
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
if (fileInfos[i].GetFilename() == fileInfos[j].GetFilename())
|
||||
{
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
{
|
||||
progressDialog.setValue(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
QString filename = ClashlessFilename(fileInfos, i);
|
||||
|
||||
if (filename == "firmware.xml")
|
||||
{
|
||||
Alerts::DisplayError("You cannot name your partition files \"firmware.xml\".\nIt is a reserved name.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!WriteTarEntry(fileInfos[i].GetFilename(), tarFile, filename))
|
||||
{
|
||||
tarFile->resize(0);
|
||||
tarFile->close();
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
progressDialog.setValue(i);
|
||||
|
||||
if (progressDialog.wasCanceled())
|
||||
{
|
||||
tarFile->resize(0);
|
||||
tarFile->close();
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
int lastSlash = firmwareInfo.GetPitFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = firmwareInfo.GetPitFilename().lastIndexOf('\\');
|
||||
|
||||
QString pitFilename = ClashlessFilename(fileInfos, firmwareInfo.GetPitFilename().mid(lastSlash + 1));
|
||||
|
||||
if (pitFilename == "firmware.xml")
|
||||
{
|
||||
Alerts::DisplayError("You cannot name your PIT file \"firmware.xml\".\nIt is a reserved name.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!WriteTarEntry(firmwareInfo.GetPitFilename(), tarFile, pitFilename))
|
||||
{
|
||||
tarFile->resize(0);
|
||||
tarFile->close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
progressDialog.setValue(progressDialog.value() + 1);
|
||||
|
||||
if (progressDialog.wasCanceled())
|
||||
{
|
||||
tarFile->resize(0);
|
||||
tarFile->close();
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!WriteTarEntry(firmwareXmlFile.fileName(), tarFile, "firmware.xml"))
|
||||
{
|
||||
tarFile->resize(0);
|
||||
tarFile->close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
progressDialog.setValue(progressDialog.value() + 1);
|
||||
progressDialog.close();
|
||||
|
||||
// Write two empty blocks to signify the end of the archive.
|
||||
char emptyEntry[TarHeader::kBlockLength];
|
||||
memset(emptyEntry, 0, TarHeader::kBlockLength);
|
||||
|
||||
tarFile->write(emptyEntry, TarHeader::kBlockLength);
|
||||
tarFile->write(emptyEntry, TarHeader::kBlockLength);
|
||||
|
||||
tarFile->close();
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool Packaging::ExtractPackage(const QString& packagePath, PackageData *packageData)
|
||||
{
|
||||
FILE *compressedPackageFile = fopen(packagePath.toStdString().c_str(), "rb");
|
||||
|
||||
if (!compressedPackageFile)
|
||||
{
|
||||
Alerts::DisplayError(QString("Failed to open package:\n%1").arg(packagePath));
|
||||
return (false);
|
||||
}
|
||||
|
||||
fseek(compressedPackageFile, 0, SEEK_END);
|
||||
quint64 compressedFileSize = ftell(compressedPackageFile);
|
||||
rewind(compressedPackageFile);
|
||||
|
||||
gzFile packageFile = gzdopen(fileno(compressedPackageFile), "rb");
|
||||
|
||||
QTemporaryFile outputTar("XXXXXX.tar");
|
||||
|
||||
if (!outputTar.open())
|
||||
{
|
||||
Alerts::DisplayError("Failed to open temporary TAR archive.");
|
||||
gzclose(packageFile);
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
char buffer[kExtractBufferLength];
|
||||
int bytesRead;
|
||||
quint64 totalBytesRead = 0;
|
||||
|
||||
QProgressDialog progressDialog("Decompressing package...", "Cancel", 0, compressedFileSize);
|
||||
progressDialog.setWindowModality(Qt::ApplicationModal);
|
||||
progressDialog.setWindowTitle("Heimdall Frontend");
|
||||
|
||||
do
|
||||
{
|
||||
bytesRead = gzread(packageFile, buffer, kExtractBufferLength);
|
||||
|
||||
if (bytesRead == -1)
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Error decompressing archive.");
|
||||
|
||||
gzclose(packageFile);
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
outputTar.write(buffer, bytesRead);
|
||||
|
||||
totalBytesRead += bytesRead;
|
||||
progressDialog.setValue(totalBytesRead);
|
||||
|
||||
if (progressDialog.wasCanceled())
|
||||
{
|
||||
gzclose(packageFile);
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
} while (bytesRead > 0);
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
outputTar.close();
|
||||
gzclose(packageFile); // Closes packageFile and compressedPackageFile
|
||||
|
||||
if (!ExtractTar(outputTar, packageData))
|
||||
return (false);
|
||||
|
||||
// Find and read firmware.xml
|
||||
for (int i = 0; i < packageData->GetFiles().length(); i++)
|
||||
{
|
||||
QTemporaryFile *file = packageData->GetFiles()[i];
|
||||
|
||||
if (file->fileTemplate() == "XXXXXX-firmware.xml")
|
||||
{
|
||||
if (!packageData->ReadFirmwareInfo(file))
|
||||
{
|
||||
packageData->Clear();
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
Alerts::DisplayError("firmware.xml is missing from the package.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool Packaging::BuildPackage(const QString& packagePath, const FirmwareInfo& firmwareInfo)
|
||||
{
|
||||
FILE *compressedPackageFile = fopen(packagePath.toStdString().c_str(), "wb");
|
||||
|
||||
if (!compressedPackageFile)
|
||||
{
|
||||
Alerts::DisplayError(QString("Failed to create package:\n%1").arg(packagePath));
|
||||
return (false);
|
||||
}
|
||||
|
||||
QTemporaryFile tar("XXXXXX.tar");
|
||||
|
||||
if (!CreateTar(firmwareInfo, &tar))
|
||||
{
|
||||
fclose(compressedPackageFile);
|
||||
remove(packagePath.toStdString().c_str());
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!tar.open())
|
||||
{
|
||||
Alerts::DisplayError(QString("Failed to open temporary file: \n%1").arg(tar.fileName()));
|
||||
|
||||
fclose(compressedPackageFile);
|
||||
remove(packagePath.toStdString().c_str());
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
gzFile packageFile = gzdopen(fileno(compressedPackageFile), "wb");
|
||||
|
||||
char buffer[kCompressBufferLength];
|
||||
qint64 totalBytesRead = 0;
|
||||
int bytesRead;
|
||||
|
||||
QProgressDialog progressDialog("Compressing package...", "Cancel", 0, tar.size());
|
||||
progressDialog.setWindowModality(Qt::ApplicationModal);
|
||||
progressDialog.setWindowTitle("Heimdall Frontend");
|
||||
|
||||
do
|
||||
{
|
||||
bytesRead = tar.read(buffer, kCompressBufferLength);
|
||||
|
||||
if (bytesRead == -1)
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Error reading temporary TAR file.");
|
||||
|
||||
gzclose(packageFile);
|
||||
remove(packagePath.toStdString().c_str());
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (gzwrite(packageFile, buffer, bytesRead) != bytesRead)
|
||||
{
|
||||
progressDialog.close();
|
||||
Alerts::DisplayError("Error compressing package.");
|
||||
|
||||
gzclose(packageFile);
|
||||
remove(packagePath.toStdString().c_str());
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
totalBytesRead += bytesRead;
|
||||
progressDialog.setValue(totalBytesRead);
|
||||
|
||||
if (progressDialog.wasCanceled())
|
||||
{
|
||||
gzclose(packageFile);
|
||||
remove(packagePath.toStdString().c_str());
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
return (false);
|
||||
}
|
||||
} while (bytesRead > 0);
|
||||
|
||||
progressDialog.close();
|
||||
|
||||
gzclose(packageFile); // Closes packageFile and compressedPackageFile
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
QString Packaging::ClashlessFilename(const QList<FileInfo>& fileInfos, int fileInfoIndex)
|
||||
{
|
||||
int lastSlash = fileInfos[fileInfoIndex].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[fileInfoIndex].GetFilename().lastIndexOf('\\');
|
||||
|
||||
QString filename = fileInfos[fileInfoIndex].GetFilename().mid(lastSlash + 1);
|
||||
unsigned int renameIndex = 0;
|
||||
|
||||
// Check for name clashes
|
||||
for (int i = 0; i < fileInfoIndex; i++)
|
||||
{
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
|
||||
|
||||
QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
|
||||
|
||||
// If the filenames are the same, but the files themselves aren't the same (i.e. not the same path), then rename.
|
||||
if (filename == otherFilename && fileInfos[i].GetFilename() != fileInfos[fileInfoIndex].GetFilename())
|
||||
renameIndex++;
|
||||
}
|
||||
|
||||
if (renameIndex > 0)
|
||||
{
|
||||
int lastPeriodIndex = filename.lastIndexOf(QChar('.'));
|
||||
QString shortFilename;
|
||||
QString fileType;
|
||||
|
||||
if (lastPeriodIndex >= 0)
|
||||
{
|
||||
shortFilename = filename.left(lastPeriodIndex);
|
||||
fileType = filename.mid(lastPeriodIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
shortFilename = filename;
|
||||
}
|
||||
|
||||
unsigned int renameIndexOffset = 0;
|
||||
bool validIndexOffset = true;
|
||||
|
||||
// Before we append a rename index we must ensure it doesn't produce further collisions.
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
|
||||
|
||||
QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
|
||||
|
||||
if (otherFilename.length() > filename.length() + 1)
|
||||
{
|
||||
QString trimmedOtherFilename = otherFilename.left(shortFilename.length());
|
||||
|
||||
if (shortFilename == trimmedOtherFilename)
|
||||
{
|
||||
lastPeriodIndex = otherFilename.lastIndexOf(QChar('.'));
|
||||
QString shortOtherFilename;
|
||||
|
||||
if (lastPeriodIndex >= 0)
|
||||
shortOtherFilename = otherFilename.left(lastPeriodIndex);
|
||||
else
|
||||
shortOtherFilename = otherFilename;
|
||||
|
||||
QRegExp renameExp("-[0-9]+");
|
||||
|
||||
if (renameExp.lastIndexIn(shortOtherFilename) == shortFilename.length())
|
||||
{
|
||||
unsigned int trailingInteger = shortOtherFilename.mid(shortFilename.length() + 1).toUInt(&validIndexOffset);
|
||||
|
||||
if (!validIndexOffset)
|
||||
break;
|
||||
|
||||
if (trailingInteger > renameIndexOffset)
|
||||
renameIndexOffset = trailingInteger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validIndexOffset)
|
||||
{
|
||||
// Ensure renaming won't involve integer overflow!
|
||||
if (renameIndex > static_cast<unsigned int>(-1) - renameIndexOffset)
|
||||
validIndexOffset = false;
|
||||
}
|
||||
|
||||
if (validIndexOffset)
|
||||
{
|
||||
shortFilename.append(QChar('-'));
|
||||
shortFilename.append(QString::number(renameIndexOffset + renameIndex));
|
||||
|
||||
return (shortFilename + fileType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback behaviour... an absolutely terrible brute force implementation!
|
||||
QString filename;
|
||||
QString renamePrefix;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
renamePrefix.append(QChar('+'));
|
||||
|
||||
for (unsigned int i = 0; i < static_cast<unsigned int>(-1); i++)
|
||||
{
|
||||
filename = shortFilename + renamePrefix + QString::number(i) + fileType;
|
||||
|
||||
bool valid = true;
|
||||
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
|
||||
|
||||
if (filename == fileInfos[i].GetFilename().mid(lastSlash + 1))
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid)
|
||||
return (filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (filename);
|
||||
}
|
||||
}
|
||||
|
||||
QString Packaging::ClashlessFilename(const QList<FileInfo>& fileInfos, const QString& filename)
|
||||
{
|
||||
unsigned int renameIndex = 0;
|
||||
|
||||
// Check for name clashes
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
|
||||
|
||||
QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
|
||||
|
||||
if (filename == otherFilename)
|
||||
renameIndex++;
|
||||
}
|
||||
|
||||
if (renameIndex > 0)
|
||||
{
|
||||
int lastPeriodIndex = filename.lastIndexOf(QChar('.'));
|
||||
QString shortFilename;
|
||||
QString fileType;
|
||||
|
||||
if (lastPeriodIndex >= 0)
|
||||
{
|
||||
shortFilename = filename.left(lastPeriodIndex);
|
||||
fileType = filename.mid(lastPeriodIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
shortFilename = filename;
|
||||
}
|
||||
|
||||
unsigned int renameIndexOffset = 0;
|
||||
bool validIndexOffset = true;
|
||||
|
||||
// Before we append a rename index we must ensure it doesn't produce further collisions.
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
|
||||
|
||||
QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
|
||||
|
||||
if (otherFilename.length() > filename.length() + 1)
|
||||
{
|
||||
QString trimmedOtherFilename = otherFilename.left(filename.length());
|
||||
|
||||
if (filename == trimmedOtherFilename)
|
||||
{
|
||||
lastPeriodIndex = otherFilename.lastIndexOf(QChar('.'));
|
||||
QString shortOtherFilename;
|
||||
|
||||
if (lastPeriodIndex >= 0)
|
||||
shortOtherFilename = otherFilename.left(lastPeriodIndex);
|
||||
else
|
||||
shortOtherFilename = otherFilename;
|
||||
|
||||
QRegExp renameExp("-[0-9]+");
|
||||
|
||||
if (renameExp.lastIndexIn(shortOtherFilename) == shortFilename.length())
|
||||
{
|
||||
unsigned int trailingInteger = shortOtherFilename.mid(shortFilename.length() + 1).toUInt(&validIndexOffset);
|
||||
|
||||
if (!validIndexOffset)
|
||||
break;
|
||||
|
||||
if (trailingInteger > renameIndexOffset)
|
||||
renameIndexOffset = trailingInteger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validIndexOffset)
|
||||
{
|
||||
// Ensure renaming won't involve integer overflow!
|
||||
if (renameIndex > static_cast<unsigned int>(-1) - renameIndexOffset)
|
||||
validIndexOffset = false;
|
||||
}
|
||||
|
||||
if (validIndexOffset)
|
||||
{
|
||||
shortFilename.append(QChar('-'));
|
||||
shortFilename.append(QString::number(renameIndexOffset + renameIndex));
|
||||
|
||||
return (shortFilename + fileType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback behaviour, brute-force/semi-random.
|
||||
bool valid;
|
||||
QString filename;
|
||||
|
||||
do
|
||||
{
|
||||
valid = true;
|
||||
|
||||
filename = shortFilename + "-";
|
||||
for (int i = 0; i < 8; i++)
|
||||
filename.append(QChar(qrand() % ('Z' - 'A' + 1) + 'A'));
|
||||
|
||||
for (int i = 0; i < fileInfos.length(); i++)
|
||||
{
|
||||
int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
|
||||
|
||||
if (lastSlash < 0)
|
||||
lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
|
||||
|
||||
if (filename == fileInfos[i].GetFilename().mid(lastSlash + 1))
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!valid);
|
||||
|
||||
return (filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (filename);
|
||||
}
|
||||
}
|
121
heimdall-frontend/source/Packaging.h
Normal file
121
heimdall-frontend/source/Packaging.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef PACKAGING_H
|
||||
#define PACKAGING_H
|
||||
|
||||
// Qt
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "PackageData.h"
|
||||
|
||||
namespace HeimdallFrontend
|
||||
{
|
||||
union TarHeader
|
||||
{
|
||||
enum
|
||||
{
|
||||
kBlockLength = 512,
|
||||
kBlockReadCount = 8,
|
||||
kBlockWriteCount = 8,
|
||||
|
||||
kTarHeaderLength = 257,
|
||||
kUstarHeaderLength = 500,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kModeOtherExecute = 1,
|
||||
kModeOtherWrite = 1 << 1,
|
||||
kModeOtherRead = 1 << 2,
|
||||
|
||||
kModeGroupExecute = 1 << 3,
|
||||
kModeGroupWrite = 1 << 4,
|
||||
kModeGroupRead = 1 << 5,
|
||||
|
||||
kModeOwnerExecute = 1 << 6,
|
||||
kModeOwnerWrite = 1 << 7,
|
||||
kModeOwnerRead = 1 << 8,
|
||||
|
||||
kModeReserved = 2 << 9,
|
||||
kModeSetGid = 2 << 10,
|
||||
kModeSetUid = 2 << 11
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
char name[100];
|
||||
char mode[8];
|
||||
char userId[8];
|
||||
char groupId[8];
|
||||
char size[12];
|
||||
char modifiedTime[12];
|
||||
char checksum[8];
|
||||
char typeFlag;
|
||||
char linkName[100];
|
||||
char magic[6];
|
||||
char version[2];
|
||||
char userName[32];
|
||||
char groupName[32];
|
||||
char devMajor[8];
|
||||
char devMinor[8];
|
||||
char prefix[155];
|
||||
} fields;
|
||||
|
||||
char buffer[kBlockLength];
|
||||
};
|
||||
|
||||
class Packaging
|
||||
{
|
||||
public:
|
||||
|
||||
// Would definitely prefer to use an enum but VC++ and GCC give conflicting warnings about C++0x or type overflow.
|
||||
static const qint64 kMaxFileSize;
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
kExtractBufferLength = 262144,
|
||||
kCompressBufferLength = 262144
|
||||
};
|
||||
|
||||
// TODO: Add support for sparse files to both methods?
|
||||
static bool ExtractTar(QTemporaryFile& tarFile, PackageData *packageData);
|
||||
|
||||
static bool WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, const QString& entryFilename);
|
||||
static bool CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarFile); // Uses original TAR format.
|
||||
|
||||
public:
|
||||
|
||||
static const char *ustarMagic;
|
||||
|
||||
static bool ExtractPackage(const QString& packagePath, PackageData *packageData);
|
||||
static bool BuildPackage(const QString& packagePath, const FirmwareInfo& firmwareInfo);
|
||||
|
||||
static QString ClashlessFilename(const QList<FileInfo>& fileInfos, int fileInfoIndex);
|
||||
static QString ClashlessFilename(const QList<FileInfo>& fileInfos, const QString& filename);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
126
heimdall-frontend/source/aboutform.cpp
Normal file
126
heimdall-frontend/source/aboutform.cpp
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Qt
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "aboutform.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
using namespace HeimdallFrontend;
|
||||
|
||||
AboutForm::AboutForm(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
// Heimdall Command Line
|
||||
QObject::connect(&heimdallProcess, SIGNAL(readyRead()), this, SLOT(HandleHeimdallStdout()));
|
||||
QObject::connect(&heimdallProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(HandleHeimdallReturned(int, QProcess::ExitStatus)));
|
||||
QObject::connect(&heimdallProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(HandleHeimdallError(QProcess::ProcessError)));
|
||||
|
||||
heimdallFailed = false;
|
||||
|
||||
RetrieveHeimdallVersion();
|
||||
}
|
||||
|
||||
void AboutForm::RetrieveHeimdallVersion(void)
|
||||
{
|
||||
heimdallProcess.setReadChannel(QProcess::StandardOutput);
|
||||
|
||||
heimdallProcess.start("heimdall", QStringList("version"));
|
||||
heimdallProcess.waitForFinished(350);
|
||||
|
||||
// OS X was playing up and not finding heimdall, so we're manually checking the PATH.
|
||||
if (heimdallFailed)
|
||||
{
|
||||
QStringList environment = QProcess::systemEnvironment();
|
||||
|
||||
QStringList paths;
|
||||
|
||||
// Ensure /usr/bin is in PATH
|
||||
for (int i = 0; i < environment.length(); i++)
|
||||
{
|
||||
if (environment[i].left(5) == "PATH=")
|
||||
{
|
||||
paths = environment[i].mid(5).split(':');
|
||||
paths.prepend("/usr/bin");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int pathIndex = -1;
|
||||
|
||||
while (heimdallFailed && ++pathIndex < paths.length())
|
||||
{
|
||||
QString heimdallPath = paths[pathIndex];
|
||||
|
||||
if (heimdallPath.length() > 0)
|
||||
{
|
||||
heimdallFailed = false;
|
||||
|
||||
if (heimdallPath[heimdallPath.length() - 1] != QDir::separator())
|
||||
heimdallPath += QDir::separator();
|
||||
|
||||
heimdallPath += "heimdall";
|
||||
|
||||
heimdallProcess.start(heimdallPath, QStringList("version"));
|
||||
heimdallProcess.waitForFinished(350);
|
||||
}
|
||||
}
|
||||
|
||||
if (heimdallFailed)
|
||||
versionCopyrightLabel->setText(versionCopyrightLabel->text().replace("%HEIMDALL-VERSION%", ""));
|
||||
}
|
||||
}
|
||||
|
||||
void AboutForm::HandleHeimdallStdout(void)
|
||||
{
|
||||
QString version = heimdallProcess.readAll();
|
||||
|
||||
if (version.length() > 0)
|
||||
{
|
||||
if (version.at(0) == QChar('v'))
|
||||
version = version.mid(1);
|
||||
|
||||
versionCopyrightLabel->setText(versionCopyrightLabel->text().replace("%HEIMDALL-VERSION%", "Version " + version + "<br />"));
|
||||
}
|
||||
}
|
||||
|
||||
void AboutForm::HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
UNUSED(exitCode);
|
||||
UNUSED(exitStatus);
|
||||
|
||||
// If for some reason %HEIMDALL-VERSION% hasn't been replaced yet, we'll replace it with an empty string.
|
||||
versionCopyrightLabel->setText(versionCopyrightLabel->text().replace("%HEIMDALL-VERSION%", ""));
|
||||
}
|
||||
|
||||
void AboutForm::HandleHeimdallError(QProcess::ProcessError error)
|
||||
{
|
||||
UNUSED(error);
|
||||
|
||||
heimdallFailed = true;
|
||||
}
|
||||
|
58
heimdall-frontend/source/aboutform.h
Normal file
58
heimdall-frontend/source/aboutform.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ABOUTFORM_H
|
||||
#define ABOUTFORM_H
|
||||
|
||||
// Qt
|
||||
#include <QProcess>
|
||||
#include <QWidget>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "ui_aboutform.h"
|
||||
|
||||
namespace HeimdallFrontend
|
||||
{
|
||||
class AboutForm : public QWidget, public Ui::AboutForm
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
bool heimdallFailed;
|
||||
QProcess heimdallProcess;
|
||||
|
||||
void RetrieveHeimdallVersion(void);
|
||||
|
||||
public:
|
||||
|
||||
explicit AboutForm(QWidget *parent = 0);
|
||||
|
||||
public slots:
|
||||
|
||||
// Heimdall Command Line
|
||||
void HandleHeimdallStdout(void);
|
||||
void HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void HandleHeimdallError(QProcess::ProcessError error);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
42
heimdall-frontend/source/main.cpp
Normal file
42
heimdall-frontend/source/main.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QtPlugin>
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "mainwindow.h"
|
||||
|
||||
#if defined(QT_STATIC)
|
||||
Q_IMPORT_PLUGIN (QWindowsIntegrationPlugin);
|
||||
#endif
|
||||
|
||||
using namespace HeimdallFrontend;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication application(argc, argv);
|
||||
|
||||
MainWindow window;
|
||||
window.show();
|
||||
|
||||
return (application.exec());
|
||||
}
|
1353
heimdall-frontend/source/mainwindow.cpp
Normal file
1353
heimdall-frontend/source/mainwindow.cpp
Normal file
File diff suppressed because it is too large
Load diff
206
heimdall-frontend/source/mainwindow.h
Normal file
206
heimdall-frontend/source/mainwindow.h
Normal file
|
@ -0,0 +1,206 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
// Qt
|
||||
#include <QList>
|
||||
#include <QMainWindow>
|
||||
#include <QProcess>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
// libpit
|
||||
#include "libpit.h"
|
||||
|
||||
// Heimdall Frontend
|
||||
#include "aboutform.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "PackageData.h"
|
||||
|
||||
using namespace libpit;
|
||||
|
||||
namespace HeimdallFrontend
|
||||
{
|
||||
enum class HeimdallState : int
|
||||
{
|
||||
Stopped = 1,
|
||||
Flashing = (int)Stopped << 1,
|
||||
DetectingDevice = (int)Flashing << 1,
|
||||
ClosingPcScreen = (int)DetectingDevice << 1,
|
||||
PrintingPit = (int)ClosingPcScreen << 1,
|
||||
DownloadingPit = (int)PrintingPit << 1,
|
||||
NoReboot = (int)DownloadingPit << 1
|
||||
};
|
||||
|
||||
inline HeimdallState operator|(HeimdallState lhs, HeimdallState rhs)
|
||||
{
|
||||
return (HeimdallState)((int)lhs | (int)rhs);
|
||||
}
|
||||
|
||||
inline HeimdallState& operator|=(HeimdallState& lhs, HeimdallState rhs)
|
||||
{
|
||||
lhs = lhs | rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline HeimdallState operator&(HeimdallState lhs, HeimdallState rhs)
|
||||
{
|
||||
lhs = (HeimdallState)((int)lhs & (int)rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline bool operator!(HeimdallState state)
|
||||
{
|
||||
return (int)state == 0;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow, public Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
kPrintPitSourceDevice = 0,
|
||||
kPrintPitSourceLocalFile
|
||||
};
|
||||
|
||||
AboutForm aboutForm;
|
||||
|
||||
QString lastDirectory;
|
||||
|
||||
int tabIndex;
|
||||
|
||||
bool heimdallFailed;
|
||||
HeimdallState heimdallState;
|
||||
QProcess heimdallProcess;
|
||||
|
||||
PackageData loadedPackageData;
|
||||
|
||||
PitData currentPitData;
|
||||
PackageData workingPackageData;
|
||||
|
||||
bool populatingPartitionNames;
|
||||
QList<unsigned int> unusedPartitionIds;
|
||||
|
||||
bool verboseOutput;
|
||||
bool resume;
|
||||
|
||||
|
||||
void StartHeimdall(const QStringList& arguments);
|
||||
|
||||
void UpdateUnusedPartitionIds(void);
|
||||
bool ReadPit(QFile *file);
|
||||
|
||||
void UpdatePackageUserInterface(void);
|
||||
|
||||
bool IsArchive(QString path);
|
||||
|
||||
QString PromptFileSelection(const QString& caption = QString("Select File"), const QString& filter = QString());
|
||||
QString PromptFileCreation(const QString& caption = QString("Save File"), const QString& filter = QString());
|
||||
|
||||
void UpdateLoadPackageInterfaceAvailability(void);
|
||||
void UpdateFlashInterfaceAvailability(void);
|
||||
void UpdateCreatePackageInterfaceAvailability(void);
|
||||
void UpdateUtilitiesInterfaceAvailability(void);
|
||||
void UpdateInterfaceAvailability(void);
|
||||
|
||||
void UpdatePartitionNamesInterface(void);
|
||||
|
||||
public:
|
||||
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
public slots:
|
||||
|
||||
void OpenDonationWebpage(void);
|
||||
void SetVerboseOutput(bool enabled);
|
||||
void ShowAbout(void);
|
||||
|
||||
void FunctionTabChanged(int index);
|
||||
|
||||
// Load Package Tab
|
||||
void SelectFirmwarePackage(void);
|
||||
void OpenDeveloperHomepage(void);
|
||||
void OpenDeveloperDonationWebpage(void);
|
||||
void LoadFirmwarePackage(void);
|
||||
|
||||
// Flash Tab
|
||||
void SelectPartitionName(int index);
|
||||
void SelectPartitionFile(void);
|
||||
|
||||
void SelectPartition(int row);
|
||||
void AddPartition(void);
|
||||
void RemovePartition(void);
|
||||
|
||||
void SelectPit(void);
|
||||
|
||||
void SetRepartition(int enabled);
|
||||
|
||||
void SetNoReboot(int enabled);
|
||||
void SetResume(bool enabled);
|
||||
void SetResume(int enabled);
|
||||
|
||||
void StartFlash(void);
|
||||
|
||||
// Create Package Tab
|
||||
void FirmwareNameChanged(const QString& text);
|
||||
void FirmwareVersionChanged(const QString& text);
|
||||
void PlatformNameChanged(const QString& text);
|
||||
void PlatformVersionChanged(const QString& text);
|
||||
|
||||
void HomepageUrlChanged(const QString& text);
|
||||
void DonateUrlChanged(const QString& text);
|
||||
|
||||
void DeveloperNameChanged(const QString& text);
|
||||
void SelectDeveloper(int row);
|
||||
void AddDeveloper(void);
|
||||
void RemoveDeveloper(void);
|
||||
|
||||
void DeviceInfoChanged(const QString& text);
|
||||
void SelectDevice(int row);
|
||||
void AddDevice(void);
|
||||
void RemoveDevice(void);
|
||||
|
||||
void BuildPackage(void);
|
||||
|
||||
// Utilities Tab
|
||||
void DetectDevice(void);
|
||||
void ClosePcScreen(void);
|
||||
|
||||
void SelectPitDestination(void);
|
||||
void DownloadPit(void);
|
||||
|
||||
void DevicePrintPitToggled(bool checked);
|
||||
void LocalFilePrintPitToggled(bool checked);
|
||||
void SelectPrintPitFile(void);
|
||||
void PrintPit(void);
|
||||
|
||||
// Heimdall Command Line
|
||||
void HandleHeimdallStdout(void);
|
||||
void HandleHeimdallReturned(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void HandleHeimdallError(QProcess::ProcessError error);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MAINWINDOW_H
|
3
heimdall/60-heimdall.rules
Normal file
3
heimdall/60-heimdall.rules
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6601", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="685d", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="68c3", MODE="0666"
|
52
heimdall/CMakeLists.txt
Normal file
52
heimdall/CMakeLists.txt
Normal file
|
@ -0,0 +1,52 @@
|
|||
cmake_minimum_required(VERSION 2.8.4)
|
||||
|
||||
project(heimdall)
|
||||
|
||||
if((NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux") AND (NOT DEFINED libusb_USE_STATIC_LIBS))
|
||||
set(libusb_USE_STATIC_LIBS YES)
|
||||
endif((NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux") AND (NOT DEFINED libusb_USE_STATIC_LIBS))
|
||||
|
||||
find_package(libusb REQUIRED)
|
||||
|
||||
set(LIBPIT_INCLUDE_DIRS
|
||||
../libpit/source)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
|
||||
|
||||
if(MINGW)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
|
||||
endif(MINGW)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_definitions(-DOS_LINUX)
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
include_directories(SYSTEM ${LIBUSB_INCLUDE_DIRS})
|
||||
|
||||
include_directories(${LIBPIT_INCLUDE_DIRS})
|
||||
|
||||
set(HEIMDALL_SOURCE_FILES
|
||||
source/Arguments.cpp
|
||||
source/BridgeManager.cpp
|
||||
source/ClosePcScreenAction.cpp
|
||||
source/DetectAction.cpp
|
||||
source/DownloadPitAction.cpp
|
||||
source/FlashAction.cpp
|
||||
source/HelpAction.cpp
|
||||
source/InfoAction.cpp
|
||||
source/Interface.cpp
|
||||
source/main.cpp
|
||||
source/PrintPitAction.cpp
|
||||
source/Utility.cpp
|
||||
source/VersionAction.cpp)
|
||||
|
||||
include(LargeFiles)
|
||||
use_large_files(heimdall YES)
|
||||
add_executable(heimdall ${HEIMDALL_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(heimdall PRIVATE pit)
|
||||
target_link_libraries(heimdall PRIVATE ${LIBUSB_LIBRARY})
|
||||
install (TARGETS heimdall
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
215
heimdall/source/Arguments.cpp
Normal file
215
heimdall/source/Arguments.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall
|
||||
#include "Arguments.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
#include "Utility.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Heimdall;
|
||||
|
||||
FlagArgument *FlagArgument::ParseArgument(const std::string& name, int argc, char **argv, int& argi)
|
||||
{
|
||||
return new FlagArgument(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
StringArgument *StringArgument::ParseArgument(const std::string& name, int argc, char **argv, int& argi)
|
||||
{
|
||||
if (++argi < argc)
|
||||
{
|
||||
return (new StringArgument(name, argv[argi]));
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Missing parameter for argument: %s\n\n", argv[argi - 1]);
|
||||
return (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
UnsignedIntegerArgument *UnsignedIntegerArgument::ParseArgument(const std::string& name, int argc, char **argv, int& argi)
|
||||
{
|
||||
UnsignedIntegerArgument *unsignedIntegerArgument = nullptr;
|
||||
|
||||
if (++argi < argc)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
if (Utility::ParseUnsignedInt(value, argv[argi]) == kNumberParsingStatusSuccess)
|
||||
unsignedIntegerArgument = new UnsignedIntegerArgument(name, value);
|
||||
else
|
||||
Interface::Print("%s must be a positive integer.", argv[argi - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Missing parameter for argument: %s\n\n", argv[argi - 1]);
|
||||
}
|
||||
|
||||
return (unsignedIntegerArgument);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Arguments::Arguments(const map<string, ArgumentType>& argumentTypes, const map<string, string>& shortArgumentAliases,
|
||||
const map<string, string>& argumentAliases) :
|
||||
argumentTypes(argumentTypes),
|
||||
shortArgumentAliases(shortArgumentAliases),
|
||||
argumentAliases(argumentAliases)
|
||||
{
|
||||
}
|
||||
|
||||
Arguments::~Arguments()
|
||||
{
|
||||
for (vector<const Argument *>::const_iterator it = argumentVector.begin(); it != argumentVector.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
bool Arguments::ParseArguments(int argc, char **argv, int argi)
|
||||
{
|
||||
for (; argi < argc; ++argi)
|
||||
{
|
||||
string argumentName = argv[argi];
|
||||
string nonwildcardArgumentName;
|
||||
|
||||
if (argumentName.find_first_of("--") == 0)
|
||||
{
|
||||
// Regular argument
|
||||
argumentName = argumentName.substr(2);
|
||||
nonwildcardArgumentName = argumentName;
|
||||
}
|
||||
else if (argumentName.find_first_of("-") == 0)
|
||||
{
|
||||
// Short argument alias
|
||||
string shortArgumentAlias = argumentName.substr(1);
|
||||
map<string, string>::const_iterator shortAliasIt = shortArgumentAliases.find(shortArgumentAlias);
|
||||
|
||||
if (shortAliasIt != shortArgumentAliases.end())
|
||||
{
|
||||
argumentName = shortAliasIt->second;
|
||||
nonwildcardArgumentName = argumentName;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown argument: %s\n\n", argv[argi]);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Invalid argument: %s\n\n", argv[argi]);
|
||||
return (false);
|
||||
}
|
||||
|
||||
map<string, ArgumentType>::const_iterator argumentTypeIt = argumentTypes.find(argumentName);
|
||||
|
||||
if (argumentTypeIt == argumentTypes.end())
|
||||
{
|
||||
// No argument with that name, maybe it's an alias...
|
||||
map<string, string>::const_iterator aliasIt = argumentAliases.find(argumentName);
|
||||
|
||||
if (aliasIt != argumentAliases.end())
|
||||
{
|
||||
argumentName = aliasIt->second;
|
||||
nonwildcardArgumentName = argumentName;
|
||||
|
||||
argumentTypeIt = argumentTypes.find(argumentName);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle wilcards
|
||||
|
||||
unsigned int unsignedIntName;
|
||||
|
||||
if (argumentTypeIt == argumentTypes.end())
|
||||
{
|
||||
// Look for the unsigned integer wildcard "%d".
|
||||
if (Utility::ParseUnsignedInt(unsignedIntName, argumentName.c_str()) == kNumberParsingStatusSuccess)
|
||||
{
|
||||
argumentTypeIt = argumentTypes.find("%d");
|
||||
argumentName = "%d";
|
||||
}
|
||||
|
||||
// Look for the string wildcard "%s"
|
||||
if (argumentTypeIt == argumentTypes.end())
|
||||
{
|
||||
argumentTypeIt = argumentTypes.find("%s");
|
||||
argumentName = "%s";
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to insert wild-cards into our argument map.
|
||||
if (argumentName == "%d" || argumentName == "%s")
|
||||
argumentName = nonwildcardArgumentName;
|
||||
|
||||
Argument *argument = nullptr;
|
||||
|
||||
if (argumentTypeIt != argumentTypes.end())
|
||||
{
|
||||
switch (argumentTypeIt->second)
|
||||
{
|
||||
case kArgumentTypeFlag:
|
||||
argument = FlagArgument::ParseArgument(argumentName, argc, argv, argi);
|
||||
break;
|
||||
|
||||
case kArgumentTypeString:
|
||||
argument = StringArgument::ParseArgument(argumentName, argc, argv, argi);
|
||||
break;
|
||||
|
||||
case kArgumentTypeUnsignedInteger:
|
||||
argument = UnsignedIntegerArgument::ParseArgument(argumentName, argc, argv, argi);
|
||||
break;
|
||||
|
||||
default:
|
||||
Interface::Print("Unknown argument type: %s\n\n", argv[argi]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown argument: %s\n\n", argv[argi]);
|
||||
}
|
||||
|
||||
if (argument)
|
||||
{
|
||||
pair<map<string, const Argument *>::iterator, bool> insertResult = argumentMap.insert(pair<string, const Argument *>(argumentName, argument));
|
||||
|
||||
if (!insertResult.second)
|
||||
{
|
||||
Interface::Print("Duplicate argument: %s (%s)\n\n", argv[argi], argumentName.c_str());
|
||||
delete argument;
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
argumentVector.push_back(argument);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
168
heimdall/source/Arguments.h
Normal file
168
heimdall/source/Arguments.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ARGUMENTS_H
|
||||
#define ARGUMENTS_H
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
kArgumentTypeFlag = 0,
|
||||
kArgumentTypeString,
|
||||
kArgumentTypeUnsignedInteger
|
||||
} ArgumentType;
|
||||
|
||||
class Argument
|
||||
{
|
||||
private:
|
||||
|
||||
std::string name;
|
||||
ArgumentType type;
|
||||
|
||||
protected:
|
||||
|
||||
Argument(const std::string& name, ArgumentType type)
|
||||
{
|
||||
this->name = name;
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Argument()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& GetName(void) const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
ArgumentType GetType(void) const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
class FlagArgument : public Argument
|
||||
{
|
||||
private:
|
||||
|
||||
FlagArgument(const std::string& name) : Argument(name, kArgumentTypeFlag)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static FlagArgument *ParseArgument(const std::string& name, int argc, char **argv, int& argi);
|
||||
};
|
||||
|
||||
class StringArgument : public Argument
|
||||
{
|
||||
private:
|
||||
|
||||
std::string value;
|
||||
|
||||
StringArgument(const std::string& name, const std::string& value) : Argument(name, kArgumentTypeString)
|
||||
{
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static StringArgument *ParseArgument(const std::string& name, int argc, char **argv, int& argi);
|
||||
|
||||
const std::string& GetValue(void) const
|
||||
{
|
||||
return (value);
|
||||
}
|
||||
};
|
||||
|
||||
class UnsignedIntegerArgument : public Argument
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int value;
|
||||
|
||||
UnsignedIntegerArgument(const std::string& name, unsigned int value) : Argument(name, kArgumentTypeUnsignedInteger)
|
||||
{
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static UnsignedIntegerArgument *ParseArgument(const std::string& name, int argc, char **argv, int& argi);
|
||||
|
||||
unsigned int GetValue(void) const
|
||||
{
|
||||
return (value);
|
||||
}
|
||||
};
|
||||
|
||||
class Arguments
|
||||
{
|
||||
private:
|
||||
|
||||
const std::map<std::string, ArgumentType> argumentTypes;
|
||||
const std::map<std::string, std::string> shortArgumentAliases;
|
||||
const std::map<std::string, std::string> argumentAliases;
|
||||
|
||||
std::vector<const Argument *> argumentVector;
|
||||
std::map<std::string, const Argument *> argumentMap;
|
||||
|
||||
public:
|
||||
|
||||
Arguments(const std::map<std::string, ArgumentType>& argumentTypes,
|
||||
const std::map<std::string, std::string>& shortArgumentAliases = (std::map<std::string, std::string>()),
|
||||
const std::map<std::string, std::string>& argumentAliases = (std::map<std::string, std::string>()));
|
||||
|
||||
~Arguments();
|
||||
|
||||
// argi is the index of the first argument to parse.
|
||||
bool ParseArguments(int argc, char **argv, int argi);
|
||||
|
||||
const Argument *GetArgument(std::string argumentName) const
|
||||
{
|
||||
std::map<std::string, const Argument *>::const_iterator it = argumentMap.find(argumentName);
|
||||
return (it != argumentMap.end() ? it->second : nullptr);
|
||||
}
|
||||
|
||||
const std::map<std::string, ArgumentType>& GetArgumentTypes(void) const
|
||||
{
|
||||
return (argumentTypes);
|
||||
}
|
||||
|
||||
const std::vector<const Argument *>& GetArguments(void) const
|
||||
{
|
||||
return (argumentVector);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
72
heimdall/source/BeginDumpPacket.h
Normal file
72
heimdall/source/BeginDumpPacket.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef BEGINDUMPPACKET_H
|
||||
#define BEGINDUMPPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "FileTransferPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class BeginDumpPacket : public FileTransferPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kChipTypeRam = 0,
|
||||
kChipTypeNand = 1
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int chipType;
|
||||
unsigned int chipId;
|
||||
|
||||
public:
|
||||
|
||||
BeginDumpPacket(unsigned int chipType, unsigned int chipId) : FileTransferPacket(FileTransferPacket::kRequestDump)
|
||||
{
|
||||
this->chipType = chipType;
|
||||
this->chipId = chipId;
|
||||
}
|
||||
|
||||
unsigned int GetChipType(void) const
|
||||
{
|
||||
return (chipType);
|
||||
}
|
||||
|
||||
unsigned int GetChipId(void) const
|
||||
{
|
||||
return (chipId);
|
||||
}
|
||||
|
||||
virtual void Pack(void)
|
||||
{
|
||||
FileTransferPacket::Pack();
|
||||
|
||||
PackInteger(FileTransferPacket::kDataSize, chipType);
|
||||
PackInteger(FileTransferPacket::kDataSize + 4, chipId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
39
heimdall/source/BeginSessionPacket.h
Normal file
39
heimdall/source/BeginSessionPacket.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef BEGINSESSIONPACKET_H
|
||||
#define BEGINSESSIONPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "SessionSetupPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class BeginSessionPacket : public SessionSetupPacket
|
||||
{
|
||||
public:
|
||||
|
||||
BeginSessionPacket() : SessionSetupPacket(SessionSetupPacket::kBeginSession)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
1277
heimdall/source/BridgeManager.cpp
Normal file
1277
heimdall/source/BridgeManager.cpp
Normal file
File diff suppressed because it is too large
Load diff
182
heimdall/source/BridgeManager.h
Normal file
182
heimdall/source/BridgeManager.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef BRIDGEMANAGER_H
|
||||
#define BRIDGEMANAGER_H
|
||||
|
||||
// libpit
|
||||
#include "libpit.h"
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
|
||||
struct libusb_context;
|
||||
struct libusb_device;
|
||||
struct libusb_device_handle;
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class InboundPacket;
|
||||
class OutboundPacket;
|
||||
|
||||
class DeviceIdentifier
|
||||
{
|
||||
public:
|
||||
|
||||
const int vendorId;
|
||||
const int productId;
|
||||
|
||||
DeviceIdentifier(int vid, int pid) :
|
||||
vendorId(vid),
|
||||
productId(pid)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class BridgeManager
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kSupportedDeviceCount = 3
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kInitialiseSucceeded = 0,
|
||||
kInitialiseFailed,
|
||||
kInitialiseDeviceNotDetected
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kVidSamsung = 0x04E8
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kPidGalaxyS = 0x6601,
|
||||
kPidGalaxyS2 = 0x685D,
|
||||
kPidDroidCharge = 0x68C3
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kDefaultTimeoutSend = 3000,
|
||||
kDefaultTimeoutReceive = 3000,
|
||||
kDefaultTimeoutEmptyTransfer = 100
|
||||
};
|
||||
|
||||
enum class UsbLogLevel
|
||||
{
|
||||
None = 0,
|
||||
Error,
|
||||
Warning,
|
||||
Info,
|
||||
Debug,
|
||||
|
||||
Default = Error
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kEmptyTransferNone = 0,
|
||||
kEmptyTransferBefore = 1,
|
||||
kEmptyTransferAfter = 1 << 1,
|
||||
kEmptyTransferBeforeAndAfter = kEmptyTransferBefore | kEmptyTransferAfter
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static const DeviceIdentifier supportedDevices[kSupportedDeviceCount];
|
||||
|
||||
bool verbose;
|
||||
|
||||
libusb_context *libusbContext;
|
||||
libusb_device_handle *deviceHandle;
|
||||
libusb_device *heimdallDevice;
|
||||
|
||||
int interfaceIndex;
|
||||
int altSettingIndex;
|
||||
int inEndpoint;
|
||||
int outEndpoint;
|
||||
|
||||
bool interfaceClaimed;
|
||||
|
||||
#ifdef OS_LINUX
|
||||
|
||||
bool detachedDriver;
|
||||
|
||||
#endif
|
||||
|
||||
unsigned int fileTransferSequenceMaxLength;
|
||||
unsigned int fileTransferPacketSize;
|
||||
unsigned int fileTransferSequenceTimeout;
|
||||
|
||||
UsbLogLevel usbLogLevel;
|
||||
|
||||
int FindDeviceInterface(void);
|
||||
bool ClaimDeviceInterface(void);
|
||||
bool SetupDeviceInterface(void);
|
||||
void ReleaseDeviceInterface(void);
|
||||
|
||||
bool InitialiseProtocol(void);
|
||||
|
||||
bool SendBulkTransfer(unsigned char *data, int length, int timeout, bool retry = true) const;
|
||||
int ReceiveBulkTransfer(unsigned char *data, int length, int timeout, bool retry = true) const;
|
||||
|
||||
public:
|
||||
|
||||
BridgeManager(bool verbose);
|
||||
~BridgeManager();
|
||||
|
||||
bool DetectDevice(void);
|
||||
int Initialise(bool resume);
|
||||
|
||||
bool BeginSession(void);
|
||||
bool EndSession(bool reboot) const;
|
||||
|
||||
bool SendPacket(OutboundPacket *packet, int timeout = kDefaultTimeoutSend, int emptyTransferFlags = kEmptyTransferAfter) const;
|
||||
bool ReceivePacket(InboundPacket *packet, int timeout = kDefaultTimeoutReceive, int emptyTransferFlags = kEmptyTransferNone) const;
|
||||
|
||||
bool RequestDeviceType(unsigned int request, int *result) const;
|
||||
|
||||
bool SendPitData(const libpit::PitData *pitData) const;
|
||||
int ReceivePitFile(unsigned char **pitBuffer) const;
|
||||
int DownloadPitFile(unsigned char **pitBuffer) const; // Thin wrapper around ReceivePitFile() with additional logging.
|
||||
|
||||
bool SendFile(FILE *file, unsigned int destination, unsigned int deviceType, unsigned int fileIdentifier = 0xFFFFFFFF) const;
|
||||
|
||||
void SetUsbLogLevel(UsbLogLevel usbLogLevel);
|
||||
|
||||
UsbLogLevel GetUsbLogLevel(void) const
|
||||
{
|
||||
return usbLogLevel;
|
||||
}
|
||||
|
||||
bool IsVerbose(void) const
|
||||
{
|
||||
return (verbose);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
130
heimdall/source/ClosePcScreenAction.cpp
Normal file
130
heimdall/source/ClosePcScreenAction.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall
|
||||
#include "Arguments.h"
|
||||
#include "BridgeManager.h"
|
||||
#include "ClosePcScreenAction.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *ClosePcScreenAction::usage = "Action: close-pc-screen\n\
|
||||
Arguments: [--verbose] [--no-reboot] [--resume] [--stdout-errors]\n\
|
||||
[--usb-log-level <none/error/warning/debug>]\n\
|
||||
Description: Attempts to get rid off the \"connect phone to PC\" screen.\n\
|
||||
Note: --no-reboot causes the device to remain in download mode after the action\n\
|
||||
is completed. If you wish to perform another action whilst remaining in\n\
|
||||
download mode, then the following action must specify the --resume flag.\n";
|
||||
|
||||
int ClosePcScreenAction::Execute(int argc, char **argv)
|
||||
{
|
||||
// Handle arguments
|
||||
|
||||
map<string, ArgumentType> argumentTypes;
|
||||
argumentTypes["no-reboot"] = kArgumentTypeFlag;
|
||||
argumentTypes["resume"] = kArgumentTypeFlag;
|
||||
argumentTypes["verbose"] = kArgumentTypeFlag;
|
||||
argumentTypes["stdout-errors"] = kArgumentTypeFlag;
|
||||
argumentTypes["usb-log-level"] = kArgumentTypeString;
|
||||
|
||||
Arguments arguments(argumentTypes);
|
||||
|
||||
if (!arguments.ParseArguments(argc, argv, 2))
|
||||
{
|
||||
Interface::Print(ClosePcScreenAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level"));
|
||||
BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default;
|
||||
|
||||
if (usbLogLevelArgument)
|
||||
{
|
||||
const string& usbLogLevelString = usbLogLevelArgument->GetValue();
|
||||
|
||||
if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::None;
|
||||
}
|
||||
else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Error;
|
||||
}
|
||||
else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Warning;
|
||||
}
|
||||
else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Info;
|
||||
}
|
||||
else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str());
|
||||
Interface::Print(ClosePcScreenAction::usage);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
bool reboot = arguments.GetArgument("no-reboot") == nullptr;
|
||||
bool resume = arguments.GetArgument("resume") != nullptr;
|
||||
bool verbose = arguments.GetArgument("verbose") != nullptr;
|
||||
|
||||
if (arguments.GetArgument("stdout-errors") != nullptr)
|
||||
Interface::SetStdoutErrors(true);
|
||||
|
||||
// Info
|
||||
|
||||
Interface::PrintReleaseInfo();
|
||||
Sleep(1000);
|
||||
|
||||
// Download PIT file from device.
|
||||
|
||||
BridgeManager *bridgeManager = new BridgeManager(verbose);
|
||||
bridgeManager->SetUsbLogLevel(usbLogLevel);
|
||||
|
||||
if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession())
|
||||
{
|
||||
delete bridgeManager;
|
||||
return (1);
|
||||
}
|
||||
|
||||
Interface::Print("Attempting to close connect to pc screen...\n");
|
||||
|
||||
bool success = bridgeManager->EndSession(reboot);
|
||||
delete bridgeManager;
|
||||
|
||||
if (success)
|
||||
{
|
||||
Interface::Print("Attempt complete\n");
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
}
|
34
heimdall/source/ClosePcScreenAction.h
Normal file
34
heimdall/source/ClosePcScreenAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef CLOSEPCSCREENACTION_H
|
||||
#define CLOSEPCSCREENACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace ClosePcScreenAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
71
heimdall/source/ControlPacket.h
Normal file
71
heimdall/source/ControlPacket.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef CONTROLPACKET_H
|
||||
#define CONTROLPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "OutboundPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class ControlPacket : public OutboundPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kControlTypeSession = 0x64,
|
||||
kControlTypePitFile = 0x65,
|
||||
kControlTypeFileTransfer = 0x66,
|
||||
kControlTypeEndSession = 0x67
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = 4
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int controlType;
|
||||
|
||||
public:
|
||||
|
||||
ControlPacket(unsigned int controlType) : OutboundPacket(1024)
|
||||
{
|
||||
this->controlType = controlType;
|
||||
}
|
||||
|
||||
unsigned int GetControlType(void) const
|
||||
{
|
||||
return (controlType);
|
||||
}
|
||||
|
||||
virtual void Pack(void)
|
||||
{
|
||||
PackInteger(0, controlType);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
104
heimdall/source/DetectAction.cpp
Normal file
104
heimdall/source/DetectAction.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall
|
||||
#include "Arguments.h"
|
||||
#include "BridgeManager.h"
|
||||
#include "DetectAction.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *DetectAction::usage = "Action: detect\n\
|
||||
Arguments: [--verbose] [--stdout-errors]\n\
|
||||
[--usb-log-level <none/error/warning/debug>]\n\
|
||||
Description: Indicates whether or not a download mode device can be detected.\n";
|
||||
|
||||
int DetectAction::Execute(int argc, char **argv)
|
||||
{
|
||||
// Handle arguments
|
||||
|
||||
map<string, ArgumentType> argumentTypes;
|
||||
argumentTypes["verbose"] = kArgumentTypeFlag;
|
||||
argumentTypes["stdout-errors"] = kArgumentTypeFlag;
|
||||
argumentTypes["usb-log-level"] = kArgumentTypeString;
|
||||
|
||||
Arguments arguments(argumentTypes);
|
||||
|
||||
if (!arguments.ParseArguments(argc, argv, 2))
|
||||
{
|
||||
Interface::Print(DetectAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
bool verbose = arguments.GetArgument("verbose") != nullptr;
|
||||
|
||||
if (arguments.GetArgument("stdout-errors") != nullptr)
|
||||
Interface::SetStdoutErrors(true);
|
||||
|
||||
const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level"));
|
||||
|
||||
BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default;
|
||||
|
||||
if (usbLogLevelArgument)
|
||||
{
|
||||
const string& usbLogLevelString = usbLogLevelArgument->GetValue();
|
||||
|
||||
if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::None;
|
||||
}
|
||||
else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Error;
|
||||
}
|
||||
else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Warning;
|
||||
}
|
||||
else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Info;
|
||||
}
|
||||
else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str());
|
||||
Interface::Print(DetectAction::usage);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
// Download PIT file from device.
|
||||
|
||||
BridgeManager *bridgeManager = new BridgeManager(verbose);
|
||||
bridgeManager->SetUsbLogLevel(usbLogLevel);
|
||||
|
||||
bool detected = bridgeManager->DetectDevice();
|
||||
|
||||
delete bridgeManager;
|
||||
|
||||
return ((detected) ? 0 : 1);
|
||||
}
|
34
heimdall/source/DetectAction.h
Normal file
34
heimdall/source/DetectAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef DETECTACTION_H
|
||||
#define DETECTACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace DetectAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
39
heimdall/source/DeviceTypePacket.h
Normal file
39
heimdall/source/DeviceTypePacket.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef DEVICETYPEPACKET_H
|
||||
#define DEVICETYPEPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "SessionSetupPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class DeviceTypePacket : public SessionSetupPacket
|
||||
{
|
||||
public:
|
||||
|
||||
DeviceTypePacket() : SessionSetupPacket(SessionSetupPacket::kDeviceType)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
171
heimdall/source/DownloadPitAction.cpp
Normal file
171
heimdall/source/DownloadPitAction.cpp
Normal file
|
@ -0,0 +1,171 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// C Standard Library
|
||||
#include <stdio.h>
|
||||
|
||||
// Heimdall
|
||||
#include "Arguments.h"
|
||||
#include "BridgeManager.h"
|
||||
#include "DownloadPitAction.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *DownloadPitAction::usage = "Action: download-pit\n\
|
||||
Arguments: --output <filename> [--verbose] [--no-reboot] [--stdout-errors]\n\
|
||||
[--usb-log-level <none/error/warning/debug>]\n\
|
||||
Description: Downloads the connected device's PIT file to the specified\n\
|
||||
output file.\n\
|
||||
Note: --no-reboot causes the device to remain in download mode after the action\n\
|
||||
is completed. If you wish to perform another action whilst remaining in\n\
|
||||
download mode, then the following action must specify the --resume flag.\n";
|
||||
|
||||
int DownloadPitAction::Execute(int argc, char **argv)
|
||||
{
|
||||
// Handle arguments
|
||||
|
||||
map<string, ArgumentType> argumentTypes;
|
||||
argumentTypes["output"] = kArgumentTypeString;
|
||||
argumentTypes["no-reboot"] = kArgumentTypeFlag;
|
||||
argumentTypes["resume"] = kArgumentTypeFlag;
|
||||
argumentTypes["verbose"] = kArgumentTypeFlag;
|
||||
argumentTypes["stdout-errors"] = kArgumentTypeFlag;
|
||||
argumentTypes["usb-log-level"] = kArgumentTypeString;
|
||||
|
||||
Arguments arguments(argumentTypes);
|
||||
|
||||
if (!arguments.ParseArguments(argc, argv, 2))
|
||||
{
|
||||
Interface::Print(DownloadPitAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
const StringArgument *outputArgument = static_cast<const StringArgument *>(arguments.GetArgument("output"));
|
||||
|
||||
if (!outputArgument)
|
||||
{
|
||||
Interface::Print("Output file was not specified.\n\n");
|
||||
Interface::Print(DownloadPitAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
bool reboot = arguments.GetArgument("no-reboot") == nullptr;
|
||||
bool resume = arguments.GetArgument("resume") != nullptr;
|
||||
bool verbose = arguments.GetArgument("verbose") != nullptr;
|
||||
|
||||
if (arguments.GetArgument("stdout-errors") != nullptr)
|
||||
Interface::SetStdoutErrors(true);
|
||||
|
||||
const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level"));
|
||||
|
||||
BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default;
|
||||
|
||||
if (usbLogLevelArgument)
|
||||
{
|
||||
const string& usbLogLevelString = usbLogLevelArgument->GetValue();
|
||||
|
||||
if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::None;
|
||||
}
|
||||
else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Error;
|
||||
}
|
||||
else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Warning;
|
||||
}
|
||||
else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Info;
|
||||
}
|
||||
else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str());
|
||||
Interface::Print(DownloadPitAction::usage);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
Interface::PrintReleaseInfo();
|
||||
Sleep(1000);
|
||||
|
||||
// Open output file
|
||||
|
||||
const char *outputFilename = outputArgument->GetValue().c_str();
|
||||
FILE *outputPitFile = FileOpen(outputFilename, "wb");
|
||||
|
||||
if (!outputPitFile)
|
||||
{
|
||||
Interface::PrintError("Failed to open output file \"%s\"\n", outputFilename);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Download PIT file from device.
|
||||
|
||||
BridgeManager *bridgeManager = new BridgeManager(verbose);
|
||||
bridgeManager->SetUsbLogLevel(usbLogLevel);
|
||||
|
||||
if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession())
|
||||
{
|
||||
FileClose(outputPitFile);
|
||||
delete bridgeManager;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
unsigned char *pitBuffer;
|
||||
int fileSize = bridgeManager->DownloadPitFile(&pitBuffer);
|
||||
|
||||
bool success = true;
|
||||
|
||||
if (fileSize > 0)
|
||||
{
|
||||
if (fwrite(pitBuffer, 1, fileSize, outputPitFile) != fileSize)
|
||||
{
|
||||
Interface::PrintError("Failed to write PIT data to output file.\n");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!bridgeManager->EndSession(reboot))
|
||||
success = false;
|
||||
|
||||
delete bridgeManager;
|
||||
|
||||
FileClose(outputPitFile);
|
||||
delete [] pitBuffer;
|
||||
|
||||
return (success ? 0 : 1);
|
||||
}
|
34
heimdall/source/DownloadPitAction.h
Normal file
34
heimdall/source/DownloadPitAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef DOWNLOADPITACTION_H
|
||||
#define DOWNLOADPITACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace DownloadPitAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
56
heimdall/source/DumpPartFileTransferPacket.h
Normal file
56
heimdall/source/DumpPartFileTransferPacket.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef DUMPPARTFILETRANSFERPACKET_H
|
||||
#define DUMPPARTFILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "FileTransferPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class DumpPartFileTransferPacket : public FileTransferPacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int partIndex;
|
||||
|
||||
public:
|
||||
|
||||
DumpPartFileTransferPacket(unsigned int partIndex) : FileTransferPacket(FileTransferPacket::kRequestPart)
|
||||
{
|
||||
this->partIndex = partIndex;
|
||||
}
|
||||
|
||||
unsigned int GetPartIndex(void) const
|
||||
{
|
||||
return (partIndex);
|
||||
}
|
||||
|
||||
virtual void Pack(void)
|
||||
{
|
||||
FileTransferPacket::Pack();
|
||||
|
||||
PackInteger(FileTransferPacket::kDataSize, partIndex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
56
heimdall/source/DumpPartPitFilePacket.h
Normal file
56
heimdall/source/DumpPartPitFilePacket.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef DUMPPARTPITFILEPACKET_H
|
||||
#define DUMPPARTPITFILEPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "PitFilePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class DumpPartPitFilePacket : public PitFilePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int partIndex;
|
||||
|
||||
public:
|
||||
|
||||
DumpPartPitFilePacket(unsigned int partIndex) : PitFilePacket(PitFilePacket::kRequestPart)
|
||||
{
|
||||
this->partIndex = partIndex;
|
||||
}
|
||||
|
||||
unsigned int GetPartIndex(void) const
|
||||
{
|
||||
return (partIndex);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
PitFilePacket::Pack();
|
||||
|
||||
PackInteger(PitFilePacket::kDataSize, partIndex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
58
heimdall/source/DumpResponse.h
Normal file
58
heimdall/source/DumpResponse.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef DUMPRESPONSE_H
|
||||
#define DUMPRESPONSE_H
|
||||
|
||||
// Heimdall
|
||||
#include "ResponsePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class DumpResponse : public ResponsePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int dumpSize;
|
||||
|
||||
public:
|
||||
|
||||
DumpResponse() : ResponsePacket(kResponseTypeFileTransfer)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int GetDumpSize(void) const
|
||||
{
|
||||
return (dumpSize);
|
||||
}
|
||||
|
||||
bool Unpack(void)
|
||||
{
|
||||
if (!ResponsePacket::Unpack())
|
||||
return (false);
|
||||
|
||||
dumpSize = UnpackInteger(ResponsePacket::kDataSize);
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
39
heimdall/source/EnableTFlashPacket.h
Normal file
39
heimdall/source/EnableTFlashPacket.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ENABLETFLASHPACKET_H
|
||||
#define ENABLETFLASHPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "SessionSetupPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class EnableTFlashPacket : public SessionSetupPacket
|
||||
{
|
||||
public:
|
||||
|
||||
EnableTFlashPacket() : SessionSetupPacket(SessionSetupPacket::kEnableTFlash)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
98
heimdall/source/EndFileTransferPacket.h
Normal file
98
heimdall/source/EndFileTransferPacket.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ENDFILETRANSFERPACKET_H
|
||||
#define ENDFILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "FileTransferPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class EndFileTransferPacket : public FileTransferPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDestinationPhone = 0x00,
|
||||
kDestinationModem = 0x01
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = FileTransferPacket::kDataSize + 16
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int destination; // PDA / Modem
|
||||
unsigned int sequenceByteCount;
|
||||
unsigned int unknown1; // EFS?
|
||||
unsigned int deviceType;
|
||||
|
||||
protected:
|
||||
|
||||
EndFileTransferPacket(unsigned int destination, unsigned int sequenceByteCount, unsigned int unknown1, unsigned int deviceType)
|
||||
: FileTransferPacket(FileTransferPacket::kRequestEnd)
|
||||
{
|
||||
this->destination = destination;
|
||||
this->sequenceByteCount = sequenceByteCount;
|
||||
this->unknown1 = unknown1;
|
||||
this->deviceType = deviceType;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
unsigned int GetDestination(void) const
|
||||
{
|
||||
return (destination);
|
||||
}
|
||||
|
||||
unsigned int GetSequenceByteCount(void) const
|
||||
{
|
||||
return (sequenceByteCount);
|
||||
}
|
||||
|
||||
unsigned int GetUnknown1(void) const
|
||||
{
|
||||
return (unknown1);
|
||||
}
|
||||
|
||||
unsigned int GetDeviceType(void) const
|
||||
{
|
||||
return (deviceType);
|
||||
}
|
||||
|
||||
virtual void Pack(void)
|
||||
{
|
||||
FileTransferPacket::Pack();
|
||||
|
||||
PackInteger(FileTransferPacket::kDataSize, destination);
|
||||
PackInteger(FileTransferPacket::kDataSize + 4, sequenceByteCount);
|
||||
PackInteger(FileTransferPacket::kDataSize + 8, unknown1);
|
||||
PackInteger(FileTransferPacket::kDataSize + 12, deviceType);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
57
heimdall/source/EndModemFileTransferPacket.h
Normal file
57
heimdall/source/EndModemFileTransferPacket.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ENDMODEMFILETRANSFERPACKET_H
|
||||
#define ENDMODEMFILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "EndFileTransferPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class EndModemFileTransferPacket : public EndFileTransferPacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int endOfFile;
|
||||
|
||||
public:
|
||||
|
||||
EndModemFileTransferPacket(unsigned int sequenceByteCount, unsigned int unknown1, unsigned int chipIdentifier, bool endOfFile)
|
||||
: EndFileTransferPacket(EndFileTransferPacket::kDestinationModem, sequenceByteCount, unknown1, chipIdentifier)
|
||||
{
|
||||
this->endOfFile = (endOfFile) ? 1 : 0;
|
||||
}
|
||||
|
||||
bool IsEndOfFile(void) const
|
||||
{
|
||||
return (endOfFile == 1);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
EndFileTransferPacket::Pack();
|
||||
|
||||
PackInteger(EndFileTransferPacket::kDataSize, endOfFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
88
heimdall/source/EndPhoneFileTransferPacket.h
Normal file
88
heimdall/source/EndPhoneFileTransferPacket.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ENDPHONEFILETRANSFERPACKET_H
|
||||
#define ENDPHONEFILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "EndFileTransferPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class EndPhoneFileTransferPacket : public EndFileTransferPacket
|
||||
{
|
||||
public:
|
||||
|
||||
/*enum
|
||||
{
|
||||
kFilePrimaryBootloader = 0x00,
|
||||
kFilePit = 0x01, // New 1.1 - Don't flash the pit this way!
|
||||
kFileSecondaryBootloader = 0x03,
|
||||
kFileSecondaryBootloaderBackup = 0x04, // New 1.1
|
||||
kFileKernel = 0x06,
|
||||
kFileRecovery = 0x07, // New 1.1
|
||||
|
||||
kFileTabletModem = 0x08, // New 1.2
|
||||
|
||||
kFileEfs = 0x14, // New 1.1
|
||||
kFileParamLfs = 0x15,
|
||||
kFileFactoryFilesystem = 0x16,
|
||||
kFileDatabaseData = 0x17,
|
||||
kFileCache = 0x18,
|
||||
|
||||
kFileModem = 0x0B // New 1.1 - Kies flashes the modem this way rather than using the EndModemFileTransferPacket.
|
||||
};*/
|
||||
|
||||
private:
|
||||
|
||||
unsigned int fileIdentifier;
|
||||
unsigned int endOfFile;
|
||||
|
||||
public:
|
||||
|
||||
EndPhoneFileTransferPacket(unsigned int sequenceByteCount, unsigned int unknown1, unsigned int chipIdentifier,
|
||||
unsigned int fileIdentifier, bool endOfFile)
|
||||
: EndFileTransferPacket(EndFileTransferPacket::kDestinationPhone, sequenceByteCount, unknown1, chipIdentifier)
|
||||
{
|
||||
this->fileIdentifier = fileIdentifier;
|
||||
this->endOfFile = (endOfFile) ? 1 : 0;
|
||||
}
|
||||
|
||||
unsigned int GetFileIdentifier(void)
|
||||
{
|
||||
return (fileIdentifier);
|
||||
}
|
||||
|
||||
bool IsEndOfFile(void) const
|
||||
{
|
||||
return (endOfFile == 1);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
EndFileTransferPacket::Pack();
|
||||
|
||||
PackInteger(EndFileTransferPacket::kDataSize, fileIdentifier);
|
||||
PackInteger(EndFileTransferPacket::kDataSize + 4, endOfFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
56
heimdall/source/EndPitFileTransferPacket.h
Normal file
56
heimdall/source/EndPitFileTransferPacket.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ENDPITFILETRANSFERPACKET_H
|
||||
#define ENDPITFILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "PitFilePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class EndPitFileTransferPacket : public PitFilePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int fileSize;
|
||||
|
||||
public:
|
||||
|
||||
EndPitFileTransferPacket(unsigned int fileSize) : PitFilePacket(PitFilePacket::kRequestEndTransfer)
|
||||
{
|
||||
this->fileSize = fileSize;
|
||||
}
|
||||
|
||||
unsigned int GetFileSize(void) const
|
||||
{
|
||||
return (fileSize);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
PitFilePacket::Pack();
|
||||
|
||||
PackInteger(PitFilePacket::kDataSize, fileSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
64
heimdall/source/EndSessionPacket.h
Normal file
64
heimdall/source/EndSessionPacket.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef ENDSESSIONPACKET_H
|
||||
#define ENDSESSIONPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "ControlPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class EndSessionPacket : public ControlPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kRequestEndSession = 0,
|
||||
kRequestRebootDevice = 1
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int request;
|
||||
|
||||
public:
|
||||
|
||||
EndSessionPacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypeEndSession)
|
||||
{
|
||||
this->request = request;
|
||||
}
|
||||
|
||||
unsigned int GetRequest(void) const
|
||||
{
|
||||
return (request);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
ControlPacket::Pack();
|
||||
|
||||
PackInteger(ControlPacket::kDataSize, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
56
heimdall/source/FilePartSizePacket.h
Normal file
56
heimdall/source/FilePartSizePacket.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef FILEPARTSIZEPACKET_H
|
||||
#define FILEPARTSIZEPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "SessionSetupPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class FilePartSizePacket : public SessionSetupPacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int filePartSize;
|
||||
|
||||
public:
|
||||
|
||||
FilePartSizePacket(unsigned int filePartSize) : SessionSetupPacket(SessionSetupPacket::kFilePartSize)
|
||||
{
|
||||
this->filePartSize = filePartSize;
|
||||
}
|
||||
|
||||
unsigned int GetFilePartSize(void) const
|
||||
{
|
||||
return filePartSize;
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
SessionSetupPacket::Pack();
|
||||
|
||||
PackInteger(SessionSetupPacket::kDataSize, filePartSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
73
heimdall/source/FileTransferPacket.h
Normal file
73
heimdall/source/FileTransferPacket.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef FILETRANSFERPACKET_H
|
||||
#define FILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "ControlPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class FileTransferPacket : public ControlPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kRequestFlash = 0x00,
|
||||
kRequestDump = 0x01,
|
||||
kRequestPart = 0x02,
|
||||
kRequestEnd = 0x03
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = ControlPacket::kDataSize + 4
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int request;
|
||||
|
||||
public:
|
||||
|
||||
FileTransferPacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypeFileTransfer)
|
||||
{
|
||||
this->request = request;
|
||||
}
|
||||
|
||||
unsigned int GetRequest(void) const
|
||||
{
|
||||
return (request);
|
||||
}
|
||||
|
||||
virtual void Pack(void)
|
||||
{
|
||||
ControlPacket::Pack();
|
||||
|
||||
PackInteger(ControlPacket::kDataSize, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
578
heimdall/source/FlashAction.cpp
Normal file
578
heimdall/source/FlashAction.cpp
Normal file
|
@ -0,0 +1,578 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// C Standard Library
|
||||
#include <stdio.h>
|
||||
|
||||
// Heimdall
|
||||
#include "Arguments.h"
|
||||
#include "BridgeManager.h"
|
||||
#include "EnableTFlashPacket.h"
|
||||
#include "EndModemFileTransferPacket.h"
|
||||
#include "EndPhoneFileTransferPacket.h"
|
||||
#include "FlashAction.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
#include "SessionSetupResponse.h"
|
||||
#include "TotalBytesPacket.h"
|
||||
#include "Utility.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libpit;
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *FlashAction::usage = "Action: flash\n\
|
||||
Arguments:\n\
|
||||
[--<partition name> <filename> ...]\n\
|
||||
[--<partition identifier> <filename> ...]\n\
|
||||
[--pit <filename>] [--verbose] [--no-reboot] [--resume] [--stdout-errors]\n\
|
||||
[--usb-log-level <none/error/warning/debug>]\n\
|
||||
or:\n\
|
||||
--repartition --pit <filename> [--<partition name> <filename> ...]\n\
|
||||
[--<partition identifier> <filename> ...] [--verbose] [--no-reboot]\n\
|
||||
[--resume] [--stdout-errors] [--usb-log-level <none/error/warning/debug>]\n\
|
||||
[--tflash]\n\
|
||||
Description: Flashes one or more firmware files to your phone. Partition names\n\
|
||||
(or identifiers) can be obtained by executing the print-pit action.\n\
|
||||
T-Flash mode allows to flash the inserted SD-card instead of the internal MMC.\n\
|
||||
Note: --no-reboot causes the device to remain in download mode after the action\n\
|
||||
is completed. If you wish to perform another action whilst remaining in\n\
|
||||
download mode, then the following action must specify the --resume flag.\n\
|
||||
WARNING: If you're repartitioning it's strongly recommended you specify\n\
|
||||
all files at your disposal.\n";
|
||||
|
||||
struct PartitionFile
|
||||
{
|
||||
const char *argumentName;
|
||||
FILE *file;
|
||||
|
||||
PartitionFile(const char *argumentName, FILE *file)
|
||||
{
|
||||
this->argumentName = argumentName;
|
||||
this->file = file;
|
||||
}
|
||||
};
|
||||
|
||||
struct PartitionFlashInfo
|
||||
{
|
||||
const PitEntry *pitEntry;
|
||||
FILE *file;
|
||||
|
||||
PartitionFlashInfo(const PitEntry *pitEntry, FILE *file)
|
||||
{
|
||||
this->pitEntry = pitEntry;
|
||||
this->file = file;
|
||||
}
|
||||
};
|
||||
|
||||
static bool openFiles(Arguments& arguments, vector<PartitionFile>& partitionFiles, FILE *& pitFile)
|
||||
{
|
||||
// Open PIT file
|
||||
|
||||
const StringArgument *pitArgument = static_cast<const StringArgument *>(arguments.GetArgument("pit"));
|
||||
|
||||
if (pitArgument)
|
||||
{
|
||||
pitFile = FileOpen(pitArgument->GetValue().c_str(), "rb");
|
||||
|
||||
if (!pitFile)
|
||||
{
|
||||
Interface::PrintError("Failed to open file \"%s\"\n", pitArgument->GetValue().c_str());
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
// Open partition files
|
||||
|
||||
for (vector<const Argument *>::const_iterator it = arguments.GetArguments().begin(); it != arguments.GetArguments().end(); it++)
|
||||
{
|
||||
const string& argumentName = (*it)->GetName();
|
||||
|
||||
// The only way an argument could exist without being in the argument types map is if it's a wild-card.
|
||||
// The "%d" wild-card refers to a partition by identifier, where as the "%s" wild-card refers to a
|
||||
// partition by name.
|
||||
|
||||
if (arguments.GetArgumentTypes().find(argumentName) == arguments.GetArgumentTypes().end())
|
||||
{
|
||||
const StringArgument *stringArgument = static_cast<const StringArgument *>(*it);
|
||||
FILE *file = FileOpen(stringArgument->GetValue().c_str(), "rb");
|
||||
|
||||
if (!file)
|
||||
{
|
||||
Interface::PrintError("Failed to open file \"%s\"\n", stringArgument->GetValue().c_str());
|
||||
return (false);
|
||||
}
|
||||
|
||||
partitionFiles.push_back(PartitionFile(argumentName.c_str(), file));
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static void closeFiles(vector<PartitionFile>& partitionFiles, FILE *& pitFile)
|
||||
{
|
||||
// Close PIT file
|
||||
|
||||
if (pitFile)
|
||||
{
|
||||
FileClose(pitFile);
|
||||
pitFile = nullptr;
|
||||
}
|
||||
|
||||
// Close partition files
|
||||
|
||||
for (vector<PartitionFile>::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++)
|
||||
FileClose(it->file);
|
||||
|
||||
partitionFiles.clear();
|
||||
}
|
||||
|
||||
static bool sendTotalTransferSize(BridgeManager *bridgeManager, const vector<PartitionFile>& partitionFiles, FILE *pitFile, bool repartition)
|
||||
{
|
||||
unsigned int totalBytes = 0;
|
||||
|
||||
for (vector<PartitionFile>::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++)
|
||||
{
|
||||
FileSeek(it->file, 0, SEEK_END);
|
||||
totalBytes += (unsigned int)FileTell(it->file);
|
||||
FileRewind(it->file);
|
||||
}
|
||||
|
||||
if (repartition)
|
||||
{
|
||||
FileSeek(pitFile, 0, SEEK_END);
|
||||
totalBytes += (unsigned int)FileTell(pitFile);
|
||||
FileRewind(pitFile);
|
||||
}
|
||||
|
||||
bool success;
|
||||
|
||||
TotalBytesPacket *totalBytesPacket = new TotalBytesPacket(totalBytes);
|
||||
success = bridgeManager->SendPacket(totalBytesPacket);
|
||||
delete totalBytesPacket;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Interface::PrintError("Failed to send total bytes packet!\n");
|
||||
return (false);
|
||||
}
|
||||
|
||||
SessionSetupResponse *totalBytesResponse = new SessionSetupResponse();
|
||||
success = bridgeManager->ReceivePacket(totalBytesResponse);
|
||||
int totalBytesResult = totalBytesResponse->GetResult();
|
||||
delete totalBytesResponse;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Interface::PrintError("Failed to receive session total bytes response!\n");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (totalBytesResult != 0)
|
||||
{
|
||||
Interface::PrintError("Unexpected session total bytes response!\nExpected: 0\nReceived:%d\n", totalBytesResult);
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool setupPartitionFlashInfo(const vector<PartitionFile>& partitionFiles, const PitData *pitData, vector<PartitionFlashInfo>& partitionFlashInfos)
|
||||
{
|
||||
for (vector<PartitionFile>::const_iterator it = partitionFiles.begin(); it != partitionFiles.end(); it++)
|
||||
{
|
||||
const PitEntry *pitEntry = nullptr;
|
||||
|
||||
// Was the argument a partition identifier?
|
||||
unsigned int partitionIdentifier;
|
||||
|
||||
if (Utility::ParseUnsignedInt(partitionIdentifier, it->argumentName) == kNumberParsingStatusSuccess)
|
||||
{
|
||||
pitEntry = pitData->FindEntry(partitionIdentifier);
|
||||
|
||||
if (!pitEntry)
|
||||
{
|
||||
Interface::PrintError("No partition with identifier \"%s\" exists in the specified PIT.\n", it->argumentName);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The argument must be an partition name e.g. "ZIMAGE"
|
||||
pitEntry = pitData->FindEntry(it->argumentName);
|
||||
|
||||
if (!pitEntry)
|
||||
{
|
||||
Interface::PrintError("Partition \"%s\" does not exist in the specified PIT.\n", it->argumentName);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
partitionFlashInfos.push_back(PartitionFlashInfo(pitEntry, it->file));
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool flashPitData(BridgeManager *bridgeManager, const PitData *pitData)
|
||||
{
|
||||
Interface::Print("Uploading PIT\n");
|
||||
|
||||
if (bridgeManager->SendPitData(pitData))
|
||||
{
|
||||
Interface::Print("PIT upload successful\n\n");
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::PrintError("PIT upload failed!\n\n");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
static bool flashFile(BridgeManager *bridgeManager, const PartitionFlashInfo& partitionFlashInfo)
|
||||
{
|
||||
if (partitionFlashInfo.pitEntry->GetBinaryType() == PitEntry::kBinaryTypeCommunicationProcessor) // Modem
|
||||
{
|
||||
Interface::Print("Uploading %s\n", partitionFlashInfo.pitEntry->GetPartitionName());
|
||||
|
||||
if (bridgeManager->SendFile(partitionFlashInfo.file, EndModemFileTransferPacket::kDestinationModem,
|
||||
partitionFlashInfo.pitEntry->GetDeviceType()))
|
||||
{
|
||||
Interface::Print("%s upload successful\n\n", partitionFlashInfo.pitEntry->GetPartitionName());
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::PrintError("%s upload failed!\n\n", partitionFlashInfo.pitEntry->GetPartitionName());
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else // partitionFlashInfo.pitEntry->GetBinaryType() == PitEntry::kBinaryTypeApplicationProcessor
|
||||
{
|
||||
Interface::Print("Uploading %s\n", partitionFlashInfo.pitEntry->GetPartitionName());
|
||||
|
||||
if (bridgeManager->SendFile(partitionFlashInfo.file, EndPhoneFileTransferPacket::kDestinationPhone,
|
||||
partitionFlashInfo.pitEntry->GetDeviceType(), partitionFlashInfo.pitEntry->GetIdentifier()))
|
||||
{
|
||||
Interface::Print("%s upload successful\n\n", partitionFlashInfo.pitEntry->GetPartitionName());
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::PrintError("%s upload failed!\n\n", partitionFlashInfo.pitEntry->GetPartitionName());
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool flashPartitions(BridgeManager *bridgeManager, const vector<PartitionFile>& partitionFiles, const PitData *pitData, bool repartition)
|
||||
{
|
||||
vector<PartitionFlashInfo> partitionFlashInfos;
|
||||
|
||||
// Map the files being flashed to partitions stored in the PIT file.
|
||||
if (!setupPartitionFlashInfo(partitionFiles, pitData, partitionFlashInfos))
|
||||
return (false);
|
||||
|
||||
// If we're repartitioning then we need to flash the PIT file first (if it is listed in the PIT file).
|
||||
if (repartition)
|
||||
{
|
||||
if (!flashPitData(bridgeManager, pitData))
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Flash partitions in the same order that arguments were specified in.
|
||||
for (vector<PartitionFlashInfo>::const_iterator it = partitionFlashInfos.begin(); it != partitionFlashInfos.end(); it++)
|
||||
{
|
||||
if (!flashFile(bridgeManager, *it))
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
static PitData *getPitData(BridgeManager *bridgeManager, FILE *pitFile, bool repartition)
|
||||
{
|
||||
PitData *pitData;
|
||||
PitData *localPitData = nullptr;
|
||||
|
||||
// If a PIT file was passed as an argument then we must unpack it.
|
||||
|
||||
if (pitFile)
|
||||
{
|
||||
// Load the local pit file into memory.
|
||||
|
||||
FileSeek(pitFile, 0, SEEK_END);
|
||||
unsigned int localPitFileSize = (unsigned int)FileTell(pitFile);
|
||||
FileRewind(pitFile);
|
||||
|
||||
unsigned char *pitFileBuffer = new unsigned char[localPitFileSize];
|
||||
memset(pitFileBuffer, 0, localPitFileSize);
|
||||
|
||||
int dataRead = fread(pitFileBuffer, 1, localPitFileSize, pitFile);
|
||||
|
||||
if (dataRead > 0)
|
||||
{
|
||||
FileRewind(pitFile);
|
||||
|
||||
localPitData = new PitData();
|
||||
localPitData->Unpack(pitFileBuffer);
|
||||
|
||||
delete [] pitFileBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::PrintError("Failed to read PIT file.\n");
|
||||
|
||||
delete [] pitFileBuffer;
|
||||
return (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (repartition)
|
||||
{
|
||||
// Use the local PIT file data.
|
||||
pitData = localPitData;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're not repartitioning then we need to retrieve the device's PIT file and unpack it.
|
||||
unsigned char *pitFileBuffer;
|
||||
|
||||
if (bridgeManager->DownloadPitFile(&pitFileBuffer) == 0)
|
||||
return (nullptr);
|
||||
|
||||
pitData = new PitData();
|
||||
pitData->Unpack(pitFileBuffer);
|
||||
|
||||
delete [] pitFileBuffer;
|
||||
|
||||
if (localPitData != nullptr)
|
||||
{
|
||||
// The user has specified a PIT without repartitioning, we should verify the local and device PIT data match!
|
||||
bool pitsMatch = pitData->Matches(localPitData);
|
||||
delete localPitData;
|
||||
|
||||
if (!pitsMatch)
|
||||
{
|
||||
Interface::Print("Local and device PIT files don't match and repartition wasn't specified!\n");
|
||||
Interface::PrintError("Flash aborted!\n");
|
||||
return (nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (pitData);
|
||||
}
|
||||
|
||||
static bool enableTFlash(BridgeManager *bridgeManager)
|
||||
{
|
||||
bool success;
|
||||
|
||||
EnableTFlashPacket *enableTFlashPacket = new EnableTFlashPacket();
|
||||
success = bridgeManager->SendPacket(enableTFlashPacket);
|
||||
delete enableTFlashPacket;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Interface::PrintError("Failed to send T-Flash packet!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
SessionSetupResponse *enableTFlashResponse = new SessionSetupResponse();
|
||||
success = bridgeManager->ReceivePacket(enableTFlashResponse, 5000);
|
||||
unsigned int result = enableTFlashResponse->GetResult();
|
||||
delete enableTFlashResponse;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Interface::PrintError("Failed to receive T-Flash response!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
Interface::PrintError("Unexpected T-Flash response!\nExpected: 0\nReceived: %d\n", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int FlashAction::Execute(int argc, char **argv)
|
||||
{
|
||||
// Setup argument types
|
||||
|
||||
map<string, ArgumentType> argumentTypes;
|
||||
map<string, string> shortArgumentAliases;
|
||||
|
||||
argumentTypes["repartition"] = kArgumentTypeFlag;
|
||||
|
||||
argumentTypes["no-reboot"] = kArgumentTypeFlag;
|
||||
argumentTypes["resume"] = kArgumentTypeFlag;
|
||||
argumentTypes["verbose"] = kArgumentTypeFlag;
|
||||
argumentTypes["stdout-errors"] = kArgumentTypeFlag;
|
||||
argumentTypes["usb-log-level"] = kArgumentTypeString;
|
||||
argumentTypes["tflash"] = kArgumentTypeFlag;
|
||||
|
||||
argumentTypes["pit"] = kArgumentTypeString;
|
||||
shortArgumentAliases["pit"] = "pit";
|
||||
|
||||
// Add wild-cards "%d" and "%s", for partition identifiers and partition names respectively.
|
||||
argumentTypes["%d"] = kArgumentTypeString;
|
||||
shortArgumentAliases["%d"] = "%d";
|
||||
|
||||
argumentTypes["%s"] = kArgumentTypeString;
|
||||
shortArgumentAliases["%s"] = "%s";
|
||||
|
||||
map<string, string> argumentAliases;
|
||||
argumentAliases["PIT"] = "pit"; // Map upper-case PIT argument (i.e. partition name) to known lower-case pit argument.
|
||||
|
||||
// Handle arguments
|
||||
|
||||
Arguments arguments(argumentTypes, shortArgumentAliases, argumentAliases);
|
||||
|
||||
if (!arguments.ParseArguments(argc, argv, 2))
|
||||
{
|
||||
Interface::Print(FlashAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
bool reboot = arguments.GetArgument("no-reboot") == nullptr;
|
||||
bool resume = arguments.GetArgument("resume") != nullptr;
|
||||
bool verbose = arguments.GetArgument("verbose") != nullptr;
|
||||
bool tflash = arguments.GetArgument("tflash") != nullptr;
|
||||
|
||||
if (arguments.GetArgument("stdout-errors") != nullptr)
|
||||
Interface::SetStdoutErrors(true);
|
||||
|
||||
const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level"));
|
||||
|
||||
BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default;
|
||||
|
||||
if (usbLogLevelArgument)
|
||||
{
|
||||
const string& usbLogLevelString = usbLogLevelArgument->GetValue();
|
||||
|
||||
if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::None;
|
||||
}
|
||||
else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Error;
|
||||
}
|
||||
else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Warning;
|
||||
}
|
||||
else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Info;
|
||||
}
|
||||
else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str());
|
||||
Interface::Print(FlashAction::usage);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
const StringArgument *pitArgument = static_cast<const StringArgument *>(arguments.GetArgument("pit"));
|
||||
|
||||
bool repartition = arguments.GetArgument("repartition") != nullptr;
|
||||
|
||||
if (repartition && !pitArgument)
|
||||
{
|
||||
Interface::Print("If you wish to repartition then a PIT file must be specified.\n\n");
|
||||
Interface::Print(FlashAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Open files
|
||||
|
||||
FILE *pitFile = nullptr;
|
||||
vector<PartitionFile> partitionFiles;
|
||||
|
||||
if (!openFiles(arguments, partitionFiles, pitFile))
|
||||
{
|
||||
closeFiles(partitionFiles, pitFile);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (partitionFiles.size() == 0)
|
||||
{
|
||||
Interface::Print(FlashAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
Interface::PrintReleaseInfo();
|
||||
Sleep(1000);
|
||||
|
||||
// Perform flash
|
||||
|
||||
BridgeManager *bridgeManager = new BridgeManager(verbose);
|
||||
bridgeManager->SetUsbLogLevel(usbLogLevel);
|
||||
|
||||
if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession())
|
||||
{
|
||||
closeFiles(partitionFiles, pitFile);
|
||||
delete bridgeManager;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (tflash && !enableTFlash(bridgeManager))
|
||||
{
|
||||
closeFiles(partitionFiles, pitFile);
|
||||
delete bridgeManager;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
bool success = sendTotalTransferSize(bridgeManager, partitionFiles, pitFile, repartition);
|
||||
|
||||
if (success)
|
||||
{
|
||||
PitData *pitData = getPitData(bridgeManager, pitFile, repartition);
|
||||
|
||||
if (pitData)
|
||||
success = flashPartitions(bridgeManager, partitionFiles, pitData, repartition);
|
||||
else
|
||||
success = false;
|
||||
|
||||
delete pitData;
|
||||
}
|
||||
|
||||
if (!bridgeManager->EndSession(reboot))
|
||||
success = false;
|
||||
|
||||
delete bridgeManager;
|
||||
|
||||
closeFiles(partitionFiles, pitFile);
|
||||
|
||||
return (success ? 0 : 1);
|
||||
}
|
34
heimdall/source/FlashAction.h
Normal file
34
heimdall/source/FlashAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef FLASHACTION_H
|
||||
#define FLASHACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace FlashAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
57
heimdall/source/FlashPartFileTransferPacket.h
Normal file
57
heimdall/source/FlashPartFileTransferPacket.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef FLASHPARTFILETRANSFERPACKET_H
|
||||
#define FLASHPARTFILETRANSFERPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "FileTransferPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class FlashPartFileTransferPacket : public FileTransferPacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int sequenceByteCount;
|
||||
|
||||
public:
|
||||
|
||||
FlashPartFileTransferPacket(unsigned int sequenceByteCount)
|
||||
: FileTransferPacket(FileTransferPacket::kRequestPart)
|
||||
{
|
||||
this->sequenceByteCount = sequenceByteCount;
|
||||
}
|
||||
|
||||
unsigned int GetSequenceByteCount(void) const
|
||||
{
|
||||
return (sequenceByteCount);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
FileTransferPacket::Pack();
|
||||
|
||||
PackInteger(FileTransferPacket::kDataSize, sequenceByteCount);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
56
heimdall/source/FlashPartPitFilePacket.h
Normal file
56
heimdall/source/FlashPartPitFilePacket.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef FLASHPARTPITFILEPACKET_H
|
||||
#define FLASHPARTPITFILEPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "PitFilePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class FlashPartPitFilePacket : public PitFilePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int partSize;
|
||||
|
||||
public:
|
||||
|
||||
FlashPartPitFilePacket(unsigned int partSize) : PitFilePacket(PitFilePacket::kRequestPart)
|
||||
{
|
||||
this->partSize = partSize;
|
||||
}
|
||||
|
||||
unsigned int GetPartSize(void) const
|
||||
{
|
||||
return (partSize);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
PitFilePacket::Pack();
|
||||
|
||||
PackInteger(PitFilePacket::kDataSize, partSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
65
heimdall/source/Heimdall.h
Normal file
65
heimdall/source/Heimdall.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef HEIMDALL_H
|
||||
#define HEIMDALL_H
|
||||
|
||||
#ifdef _MSC_VER // Microsoft Visual C Standard Library
|
||||
|
||||
#include <Windows.h>
|
||||
#undef GetBinaryType
|
||||
|
||||
#ifndef va_copy
|
||||
#define va_copy(d, s) ((d) = (s))
|
||||
#endif
|
||||
|
||||
#define FileOpen(FILE, MODE) fopen(FILE, MODE)
|
||||
#define FileClose(FILE) fclose(FILE)
|
||||
#define FileSeek(FILE, OFFSET, ORIGIN) _fseeki64(FILE, OFFSET, ORIGIN)
|
||||
#define FileTell(FILE) _ftelli64(FILE)
|
||||
#define FileRewind(FILE) rewind(FILE)
|
||||
|
||||
#else // POSIX Standard Library
|
||||
|
||||
#ifdef AUTOCONF
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define Sleep(t) usleep(1000*t)
|
||||
|
||||
#define FileOpen(FILE, MODE) fopen(FILE, MODE)
|
||||
#define FileClose(FILE) fclose(FILE)
|
||||
#define FileSeek(FILE, OFFSET, ORIGIN) fseeko(FILE, OFFSET, ORIGIN)
|
||||
#define FileTell(FILE) ftello(FILE)
|
||||
#define FileRewind(FILE) rewind(FILE)
|
||||
|
||||
#endif
|
||||
|
||||
#if (!(defined _MSC_VER) || (_MSC_VER < 1700))
|
||||
|
||||
#ifndef nullptr
|
||||
#define nullptr 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
35
heimdall/source/HelpAction.cpp
Normal file
35
heimdall/source/HelpAction.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
#include "HelpAction.h"
|
||||
#include "Interface.h"
|
||||
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *HelpAction::usage = "Action: help\n\
|
||||
Description: Displays this dialogue.\n";
|
||||
|
||||
int HelpAction::Execute(int argc, char **argv)
|
||||
{
|
||||
Interface::PrintUsage();
|
||||
return (0);
|
||||
}
|
34
heimdall/source/HelpAction.h
Normal file
34
heimdall/source/HelpAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef HELPACTION_H
|
||||
#define HELPACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace HelpAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
77
heimdall/source/InboundPacket.h
Normal file
77
heimdall/source/InboundPacket.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef INBOUNDPACKET_H
|
||||
#define INBOUNDPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "Packet.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class InboundPacket : public Packet
|
||||
{
|
||||
private:
|
||||
|
||||
bool sizeVariable;
|
||||
unsigned int receivedSize;
|
||||
|
||||
protected:
|
||||
|
||||
unsigned int UnpackInteger(unsigned int offset) const
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
unsigned int value = (data[offset] << 24) | (data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) | data[offset + 3];
|
||||
#else
|
||||
// Flip endianness
|
||||
unsigned int value = data[offset] | (data[offset + 1] << 8) |
|
||||
(data[offset + 2] << 16) | (data[offset + 3] << 24);
|
||||
#endif
|
||||
return (value);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
InboundPacket(unsigned int size, bool sizeVariable = false) : Packet(size)
|
||||
{
|
||||
this->sizeVariable = sizeVariable;
|
||||
}
|
||||
|
||||
bool IsSizeVariable(void) const
|
||||
{
|
||||
return (sizeVariable);
|
||||
}
|
||||
|
||||
unsigned int GetReceivedSize(void) const
|
||||
{
|
||||
return (receivedSize);
|
||||
}
|
||||
|
||||
void SetReceivedSize(unsigned int receivedSize)
|
||||
{
|
||||
this->receivedSize = receivedSize;
|
||||
}
|
||||
|
||||
virtual bool Unpack(void) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
35
heimdall/source/InfoAction.cpp
Normal file
35
heimdall/source/InfoAction.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
#include "InfoAction.h"
|
||||
#include "Interface.h"
|
||||
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *InfoAction::usage = "Action: info\n\
|
||||
Description: Displays information about Heimdall.\n";
|
||||
|
||||
int InfoAction::Execute(int argc, char **argv)
|
||||
{
|
||||
Interface::PrintFullInfo();
|
||||
return (0);
|
||||
}
|
34
heimdall/source/InfoAction.h
Normal file
34
heimdall/source/InfoAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef INFOACTION_H
|
||||
#define INFOACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace InfoAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
332
heimdall/source/Interface.cpp
Normal file
332
heimdall/source/Interface.cpp
Normal file
|
@ -0,0 +1,332 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include <stdio.h>
|
||||
|
||||
// Heimdall
|
||||
#include "ClosePcScreenAction.h"
|
||||
#include "DetectAction.h"
|
||||
#include "DownloadPitAction.h"
|
||||
#include "FlashAction.h"
|
||||
#include "HelpAction.h"
|
||||
#include "InfoAction.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
#include "PrintPitAction.h"
|
||||
#include "VersionAction.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libpit;
|
||||
using namespace Heimdall;
|
||||
|
||||
map<string, Interface::ActionInfo> actionMap;
|
||||
bool stdoutErrors = false;
|
||||
|
||||
const char *version = "v1.4.2";
|
||||
const char *actionUsage = "Usage: heimdall <action> <action arguments>\n";
|
||||
|
||||
const char *releaseInfo = "Heimdall %s\n\n\
|
||||
Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna\n\
|
||||
http://www.glassechidna.com.au/\n\n\
|
||||
This software is provided free of charge. Copying and redistribution is\nencouraged.\n\n\
|
||||
If you appreciate this software and you would like to support future\ndevelopment please consider donating:\n\
|
||||
http://www.glassechidna.com.au/donate/\n\n";
|
||||
|
||||
static const char *extraInfo = "Heimdall utilises libusbx for all USB communication:\n\
|
||||
http://www.libusb.org/\n\
|
||||
\n\
|
||||
libusbx is licensed under the LGPL-2.1:\n\
|
||||
http://www.gnu.org/licenses/licenses.html#LGPL\n\n";
|
||||
|
||||
void populateActionMap(void)
|
||||
{
|
||||
actionMap["close-pc-screen"] = Interface::ActionInfo(&ClosePcScreenAction::Execute, ClosePcScreenAction::usage);
|
||||
actionMap["detect"] = Interface::ActionInfo(&DetectAction::Execute, DetectAction::usage);
|
||||
actionMap["download-pit"] = Interface::ActionInfo(&DownloadPitAction::Execute, DownloadPitAction::usage);
|
||||
actionMap["flash"] = Interface::ActionInfo(&FlashAction::Execute, FlashAction::usage);
|
||||
actionMap["help"] = Interface::ActionInfo(&HelpAction::Execute, HelpAction::usage);
|
||||
actionMap["info"] = Interface::ActionInfo(&InfoAction::Execute, InfoAction::usage);
|
||||
actionMap["print-pit"] = Interface::ActionInfo(&PrintPitAction::Execute, PrintPitAction::usage);
|
||||
actionMap["version"] = Interface::ActionInfo(&VersionAction::Execute, VersionAction::usage);
|
||||
}
|
||||
|
||||
const map<string, Interface::ActionInfo>& Interface::GetActionMap(void)
|
||||
{
|
||||
if (actionMap.size() == 0)
|
||||
populateActionMap();
|
||||
|
||||
return actionMap;
|
||||
}
|
||||
|
||||
void Interface::Print(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
vfprintf(stdout, format, args);
|
||||
fflush(stdout);
|
||||
|
||||
va_end(args);
|
||||
|
||||
}
|
||||
|
||||
void Interface::PrintWarning(const char *format, ...)
|
||||
{
|
||||
va_list stderrArgs;
|
||||
va_start(stderrArgs, format);
|
||||
|
||||
if (stdoutErrors)
|
||||
{
|
||||
va_list stdoutArgs;
|
||||
va_copy(stdoutArgs, stderrArgs);
|
||||
fprintf(stdout, "WARNING: ");
|
||||
vfprintf(stdout, format, stdoutArgs);
|
||||
fflush(stdout);
|
||||
va_end(stdoutArgs);
|
||||
}
|
||||
|
||||
fprintf(stderr, "WARNING: ");
|
||||
vfprintf(stderr, format, stderrArgs);
|
||||
fflush(stderr);
|
||||
|
||||
va_end(stderrArgs);
|
||||
}
|
||||
|
||||
void Interface::PrintWarningSameLine(const char *format, ...)
|
||||
{
|
||||
va_list stderrArgs;
|
||||
va_start(stderrArgs, format);
|
||||
|
||||
if (stdoutErrors)
|
||||
{
|
||||
va_list stdoutArgs;
|
||||
va_copy(stdoutArgs, stderrArgs);
|
||||
vfprintf(stdout, format, stdoutArgs);
|
||||
fflush(stdout);
|
||||
va_end(stdoutArgs);
|
||||
}
|
||||
|
||||
vfprintf(stderr, format, stderrArgs);
|
||||
fflush(stderr);
|
||||
|
||||
va_end(stderrArgs);
|
||||
}
|
||||
|
||||
void Interface::PrintError(const char *format, ...)
|
||||
{
|
||||
va_list stderrArgs;
|
||||
va_start(stderrArgs, format);
|
||||
|
||||
if (stdoutErrors)
|
||||
{
|
||||
va_list stdoutArgs;
|
||||
va_copy(stdoutArgs, stderrArgs);
|
||||
fprintf(stdout, "ERROR: ");
|
||||
vfprintf(stdout, format, stdoutArgs);
|
||||
fflush(stdout);
|
||||
va_end(stdoutArgs);
|
||||
}
|
||||
|
||||
fprintf(stderr, "ERROR: ");
|
||||
vfprintf(stderr, format, stderrArgs);
|
||||
fflush(stderr);
|
||||
|
||||
va_end(stderrArgs);
|
||||
}
|
||||
|
||||
void Interface::PrintErrorSameLine(const char *format, ...)
|
||||
{
|
||||
va_list stderrArgs;
|
||||
va_start(stderrArgs, format);
|
||||
|
||||
if (stdoutErrors)
|
||||
{
|
||||
va_list stdoutArgs;
|
||||
va_copy(stdoutArgs, stderrArgs);
|
||||
vfprintf(stdout, format, stdoutArgs);
|
||||
fflush(stdout);
|
||||
va_end(stdoutArgs);
|
||||
}
|
||||
|
||||
vfprintf(stderr, format, stderrArgs);
|
||||
fflush(stderr);
|
||||
|
||||
va_end(stderrArgs);
|
||||
}
|
||||
|
||||
void Interface::PrintVersion(void)
|
||||
{
|
||||
Interface::Print("%s\n", version);
|
||||
}
|
||||
|
||||
void Interface::PrintUsage(void)
|
||||
{
|
||||
const map<string, ActionInfo>& actionMap = Interface::GetActionMap();
|
||||
|
||||
Interface::Print(actionUsage);
|
||||
|
||||
for (map<string, ActionInfo>::const_iterator it = actionMap.begin(); it != actionMap.end(); it++)
|
||||
Interface::Print("\n%s", it->second.usage);
|
||||
}
|
||||
|
||||
void Interface::PrintReleaseInfo(void)
|
||||
{
|
||||
Interface::Print(releaseInfo, version);
|
||||
}
|
||||
|
||||
void Interface::PrintFullInfo(void)
|
||||
{
|
||||
Interface::Print(releaseInfo, version);
|
||||
Interface::Print(extraInfo);
|
||||
}
|
||||
|
||||
void Interface::PrintDeviceDetectionFailed(void)
|
||||
{
|
||||
Interface::PrintError("Failed to detect compatible download-mode device.\n");
|
||||
}
|
||||
|
||||
void Interface::PrintPit(const PitData *pitData)
|
||||
{
|
||||
Interface::Print("Entry Count: %d\n", pitData->GetEntryCount());
|
||||
|
||||
Interface::Print("Unknown 1: %d\n", pitData->GetUnknown1());
|
||||
Interface::Print("Unknown 2: %d\n", pitData->GetUnknown2());
|
||||
Interface::Print("Unknown 3: %d\n", pitData->GetUnknown3());
|
||||
Interface::Print("Unknown 4: %d\n", pitData->GetUnknown4());
|
||||
Interface::Print("Unknown 5: %d\n", pitData->GetUnknown5());
|
||||
Interface::Print("Unknown 6: %d\n", pitData->GetUnknown6());
|
||||
Interface::Print("Unknown 7: %d\n", pitData->GetUnknown7());
|
||||
Interface::Print("Unknown 8: %d\n", pitData->GetUnknown8());
|
||||
|
||||
for (unsigned int i = 0; i < pitData->GetEntryCount(); i++)
|
||||
{
|
||||
const PitEntry *entry = pitData->GetEntry(i);
|
||||
|
||||
Interface::Print("\n\n--- Entry #%d ---\n", i);
|
||||
Interface::Print("Binary Type: %d (", entry->GetBinaryType());
|
||||
|
||||
switch (entry->GetBinaryType())
|
||||
{
|
||||
case PitEntry::kBinaryTypeApplicationProcessor:
|
||||
Interface::Print("AP");
|
||||
break;
|
||||
|
||||
case PitEntry::kBinaryTypeCommunicationProcessor:
|
||||
Interface::Print("CP");
|
||||
break;
|
||||
|
||||
default:
|
||||
Interface::Print("Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
Interface::Print(")\n");
|
||||
|
||||
Interface::Print("Device Type: %d (", entry->GetDeviceType());
|
||||
|
||||
switch (entry->GetDeviceType())
|
||||
{
|
||||
case PitEntry::kDeviceTypeOneNand:
|
||||
Interface::Print("OneNAND");
|
||||
break;
|
||||
|
||||
case PitEntry::kDeviceTypeFile:
|
||||
Interface::Print("File/FAT");
|
||||
break;
|
||||
|
||||
case PitEntry::kDeviceTypeMMC:
|
||||
Interface::Print("MMC");
|
||||
break;
|
||||
|
||||
case PitEntry::kDeviceTypeAll:
|
||||
Interface::Print("All (?)");
|
||||
break;
|
||||
|
||||
default:
|
||||
Interface::Print("Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
Interface::Print(")\n");
|
||||
|
||||
Interface::Print("Identifier: %d\n", entry->GetIdentifier());
|
||||
|
||||
Interface::Print("Attributes: %d (", entry->GetAttributes());
|
||||
|
||||
if (entry->GetAttributes() & PitEntry::kAttributeSTL)
|
||||
Interface::Print("STL ");
|
||||
|
||||
/*if (entry->GetAttributes() & PitEntry::kAttributeBML)
|
||||
Interface::Print("BML ");*/
|
||||
|
||||
if (entry->GetAttributes() & PitEntry::kAttributeWrite)
|
||||
Interface::Print("Read/Write");
|
||||
else
|
||||
Interface::Print("Read-Only");
|
||||
|
||||
Interface::Print(")\n");
|
||||
|
||||
Interface::Print("Update Attributes: %d", entry->GetUpdateAttributes());
|
||||
|
||||
if (entry->GetUpdateAttributes())
|
||||
{
|
||||
Interface::Print(" (");
|
||||
|
||||
if (entry->GetUpdateAttributes() & PitEntry::kUpdateAttributeFota)
|
||||
{
|
||||
if (entry->GetUpdateAttributes() & PitEntry::kUpdateAttributeSecure)
|
||||
Interface::Print("FOTA, Secure");
|
||||
else
|
||||
Interface::Print("FOTA");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry->GetUpdateAttributes() & PitEntry::kUpdateAttributeSecure)
|
||||
Interface::Print("Secure");
|
||||
}
|
||||
|
||||
Interface::Print(")\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("\n");
|
||||
}
|
||||
|
||||
Interface::Print("Partition Block Size/Offset: %d\n", entry->GetBlockSizeOrOffset());
|
||||
Interface::Print("Partition Block Count: %d\n", entry->GetBlockCount());
|
||||
|
||||
Interface::Print("File Offset (Obsolete): %d\n", entry->GetFileOffset());
|
||||
Interface::Print("File Size (Obsolete): %d\n", entry->GetFileSize());
|
||||
|
||||
Interface::Print("Partition Name: %s\n", entry->GetPartitionName());
|
||||
Interface::Print("Flash Filename: %s\n", entry->GetFlashFilename());
|
||||
Interface::Print("FOTA Filename: %s\n", entry->GetFotaFilename());
|
||||
}
|
||||
|
||||
Interface::Print("\n");
|
||||
}
|
||||
|
||||
void Interface::SetStdoutErrors(bool enabled)
|
||||
{
|
||||
stdoutErrors = enabled;
|
||||
}
|
80
heimdall/source/Interface.h
Normal file
80
heimdall/source/Interface.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef INTERFACE_H
|
||||
#define INTERFACE_H
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// libpit
|
||||
#include "libpit.h"
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
typedef int (*ActionExecuteFunction)(int, char **);
|
||||
|
||||
typedef struct ActionInfo
|
||||
{
|
||||
ActionExecuteFunction executeFunction;
|
||||
const char *usage;
|
||||
|
||||
ActionInfo()
|
||||
{
|
||||
executeFunction = nullptr;
|
||||
usage = nullptr;
|
||||
}
|
||||
|
||||
ActionInfo(ActionExecuteFunction executeFunction, const char *usage)
|
||||
{
|
||||
this->executeFunction = executeFunction;
|
||||
this->usage = usage;
|
||||
}
|
||||
|
||||
} ActionInfo;
|
||||
|
||||
const std::map<std::string, ActionInfo>& GetActionMap(void);
|
||||
|
||||
void Print(const char *format, ...);
|
||||
void PrintWarning(const char *format, ...);
|
||||
void PrintWarningSameLine(const char *format, ...);
|
||||
void PrintError(const char *format, ...);
|
||||
void PrintErrorSameLine(const char *format, ...);
|
||||
|
||||
void PrintVersion(void);
|
||||
void PrintUsage(void);
|
||||
void PrintReleaseInfo(void);
|
||||
void PrintFullInfo(void);
|
||||
|
||||
void PrintDeviceDetectionFailed(void);
|
||||
|
||||
void PrintPit(const libpit::PitData *pitData);
|
||||
|
||||
void SetStdoutErrors(bool enabled);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
71
heimdall/source/OutboundPacket.h
Normal file
71
heimdall/source/OutboundPacket.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef OUTBOUNDPACKET_H
|
||||
#define OUTBOUNDPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "Packet.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class OutboundPacket : public Packet
|
||||
{
|
||||
protected:
|
||||
|
||||
void PackInteger(unsigned int offset, unsigned int value)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
data[offset] = (value & 0xFF000000) >> 24;
|
||||
data[offset + 1] = (value & 0x00FF0000) >> 16;
|
||||
data[offset + 2] = (value & 0x0000FF00) >> 8;
|
||||
data[offset + 3] = value & 0x000000FF;
|
||||
#else
|
||||
// Flip endianness
|
||||
data[offset] = value & 0x000000FF;
|
||||
data[offset + 1] = (value & 0x0000FF00) >> 8;
|
||||
data[offset + 2] = (value & 0x00FF0000) >> 16;
|
||||
data[offset + 3] = (value & 0xFF000000) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PackShort(unsigned int offset, unsigned short value)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
data[offset] = (value & 0xFF00) >> 8;
|
||||
data[offset + 1] = value & 0x00FF;
|
||||
#else
|
||||
// Flip endianness
|
||||
data[offset] = value & 0x00FF;
|
||||
data[offset + 1] = (value & 0xFF00) >> 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
OutboundPacket(unsigned int size) : Packet(size)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Pack(void) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
65
heimdall/source/Packet.h
Normal file
65
heimdall/source/Packet.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef PACKET_H
|
||||
#define PACKET_H
|
||||
|
||||
// C++ Standard Library
|
||||
#include <cstring>
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class Packet
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int size;
|
||||
|
||||
protected:
|
||||
|
||||
unsigned char *data;
|
||||
|
||||
public:
|
||||
|
||||
Packet(unsigned int size)
|
||||
{
|
||||
this->size = size;
|
||||
data = new unsigned char[size];
|
||||
memset(data, 0, size);
|
||||
}
|
||||
|
||||
~Packet()
|
||||
{
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
unsigned int GetSize(void) const
|
||||
{
|
||||
return (size);
|
||||
}
|
||||
|
||||
unsigned char *GetData(void)
|
||||
{
|
||||
return (data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
73
heimdall/source/PitFilePacket.h
Normal file
73
heimdall/source/PitFilePacket.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef PITFILEPACKET_H
|
||||
#define PITFILEPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "ControlPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class PitFilePacket : public ControlPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kRequestFlash = 0x00,
|
||||
kRequestDump = 0x01,
|
||||
kRequestPart = 0x02,
|
||||
kRequestEndTransfer = 0x03
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = ControlPacket::kDataSize + 4
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int request;
|
||||
|
||||
public:
|
||||
|
||||
PitFilePacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypePitFile)
|
||||
{
|
||||
this->request = request;
|
||||
}
|
||||
|
||||
unsigned int GetRequest(void) const
|
||||
{
|
||||
return (request);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
ControlPacket::Pack();
|
||||
|
||||
PackInteger(ControlPacket::kDataSize, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
58
heimdall/source/PitFileResponse.h
Normal file
58
heimdall/source/PitFileResponse.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef PITFILERESPONSE_H
|
||||
#define PITFILERESPONSE_H
|
||||
|
||||
// Heimdall
|
||||
#include "ResponsePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class PitFileResponse : public ResponsePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int fileSize;
|
||||
|
||||
public:
|
||||
|
||||
PitFileResponse() : ResponsePacket(ResponsePacket::kResponseTypePitFile)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int GetFileSize(void) const
|
||||
{
|
||||
return (fileSize);
|
||||
}
|
||||
|
||||
bool Unpack(void)
|
||||
{
|
||||
if (!ResponsePacket::Unpack())
|
||||
return (false);
|
||||
|
||||
fileSize = UnpackInteger(ResponsePacket::kDataSize);
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
197
heimdall/source/PrintPitAction.cpp
Normal file
197
heimdall/source/PrintPitAction.cpp
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// C Standard Library
|
||||
#include <stdio.h>
|
||||
|
||||
// Heimdall
|
||||
#include "Arguments.h"
|
||||
#include "BridgeManager.h"
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
#include "PrintPitAction.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libpit;
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *PrintPitAction::usage = "Action: print-pit\n\
|
||||
Arguments: [--file <filename>] [--verbose] [--no-reboot] [--stdout-errors]\n\
|
||||
[--usb-log-level <none/error/warning/debug>]\n\
|
||||
Description: Prints the contents of a PIT file in a human readable format. If\n\
|
||||
a filename is not provided then Heimdall retrieves the PIT file from the \n\
|
||||
connected device.\n\
|
||||
Note: --no-reboot causes the device to remain in download mode after the action\n\
|
||||
is completed. If you wish to perform another action whilst remaining in\n\
|
||||
download mode, then the following action must specify the --resume flag.\n";
|
||||
|
||||
int PrintPitAction::Execute(int argc, char **argv)
|
||||
{
|
||||
// Handle arguments
|
||||
|
||||
map<string, ArgumentType> argumentTypes;
|
||||
argumentTypes["file"] = kArgumentTypeString;
|
||||
argumentTypes["no-reboot"] = kArgumentTypeFlag;
|
||||
argumentTypes["resume"] = kArgumentTypeFlag;
|
||||
argumentTypes["verbose"] = kArgumentTypeFlag;
|
||||
argumentTypes["stdout-errors"] = kArgumentTypeFlag;
|
||||
argumentTypes["usb-log-level"] = kArgumentTypeString;
|
||||
|
||||
Arguments arguments(argumentTypes);
|
||||
|
||||
if (!arguments.ParseArguments(argc, argv, 2))
|
||||
{
|
||||
Interface::Print(PrintPitAction::usage);
|
||||
return (0);
|
||||
}
|
||||
|
||||
const StringArgument *fileArgument = static_cast<const StringArgument *>(arguments.GetArgument("file"));
|
||||
|
||||
bool reboot = arguments.GetArgument("no-reboot") == nullptr;
|
||||
bool resume = arguments.GetArgument("resume") != nullptr;
|
||||
bool verbose = arguments.GetArgument("verbose") != nullptr;
|
||||
|
||||
if (arguments.GetArgument("stdout-errors") != nullptr)
|
||||
Interface::SetStdoutErrors(true);
|
||||
|
||||
const StringArgument *usbLogLevelArgument = static_cast<const StringArgument *>(arguments.GetArgument("usb-log-level"));
|
||||
|
||||
BridgeManager::UsbLogLevel usbLogLevel = BridgeManager::UsbLogLevel::Default;
|
||||
|
||||
if (usbLogLevelArgument)
|
||||
{
|
||||
const string& usbLogLevelString = usbLogLevelArgument->GetValue();
|
||||
|
||||
if (usbLogLevelString.compare("none") == 0 || usbLogLevelString.compare("NONE") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::None;
|
||||
}
|
||||
else if (usbLogLevelString.compare("error") == 0 || usbLogLevelString.compare("ERROR") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Error;
|
||||
}
|
||||
else if (usbLogLevelString.compare("warning") == 0 || usbLogLevelString.compare("WARNING") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Warning;
|
||||
}
|
||||
else if (usbLogLevelString.compare("info") == 0 || usbLogLevelString.compare("INFO") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Info;
|
||||
}
|
||||
else if (usbLogLevelString.compare("debug") == 0 || usbLogLevelString.compare("DEBUG") == 0)
|
||||
{
|
||||
usbLogLevel = BridgeManager::UsbLogLevel::Debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::Print("Unknown USB log level: %s\n\n", usbLogLevelString.c_str());
|
||||
Interface::Print(PrintPitAction::usage);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
// Open file (if specified).
|
||||
|
||||
FILE *localPitFile = nullptr;
|
||||
|
||||
if (fileArgument)
|
||||
{
|
||||
const char *filename = fileArgument->GetValue().c_str();
|
||||
|
||||
localPitFile = FileOpen(filename, "rb");
|
||||
|
||||
if (!localPitFile)
|
||||
{
|
||||
Interface::PrintError("Failed to open file \"%s\"\n", filename);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
Interface::PrintReleaseInfo();
|
||||
Sleep(1000);
|
||||
|
||||
if (localPitFile)
|
||||
{
|
||||
// Print PIT from file; there's no need for a BridgeManager.
|
||||
|
||||
FileSeek(localPitFile, 0, SEEK_END);
|
||||
unsigned int localPitFileSize = (unsigned int)FileTell(localPitFile);
|
||||
FileRewind(localPitFile);
|
||||
|
||||
// Load the local pit file into memory.
|
||||
unsigned char *pitFileBuffer = new unsigned char[localPitFileSize];
|
||||
(void)fread(pitFileBuffer, 1, localPitFileSize, localPitFile);
|
||||
FileClose(localPitFile);
|
||||
|
||||
PitData *pitData = new PitData();
|
||||
pitData->Unpack(pitFileBuffer);
|
||||
|
||||
delete [] pitFileBuffer;
|
||||
|
||||
Interface::PrintPit(pitData);
|
||||
delete pitData;
|
||||
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print PIT from a device.
|
||||
|
||||
BridgeManager *bridgeManager = new BridgeManager(verbose);
|
||||
bridgeManager->SetUsbLogLevel(usbLogLevel);
|
||||
|
||||
if (bridgeManager->Initialise(resume) != BridgeManager::kInitialiseSucceeded || !bridgeManager->BeginSession())
|
||||
{
|
||||
delete bridgeManager;
|
||||
return (1);
|
||||
}
|
||||
|
||||
unsigned char *devicePit;
|
||||
bool success = bridgeManager->DownloadPitFile(&devicePit) != 0;
|
||||
|
||||
if (success)
|
||||
{
|
||||
PitData *pitData = new PitData();
|
||||
|
||||
if (pitData->Unpack(devicePit))
|
||||
{
|
||||
Interface::PrintPit(pitData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface::PrintError("Failed to unpack device's PIT file!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
delete pitData;
|
||||
}
|
||||
|
||||
delete [] devicePit;
|
||||
|
||||
if (!bridgeManager->EndSession(reboot))
|
||||
success = false;
|
||||
|
||||
delete bridgeManager;
|
||||
|
||||
return (success ? 0 : 1);
|
||||
}
|
||||
}
|
34
heimdall/source/PrintPitAction.h
Normal file
34
heimdall/source/PrintPitAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef PRINTPITACTION_H
|
||||
#define PRINTPITACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace PrintPitAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
49
heimdall/source/ReceiveFilePartPacket.h
Normal file
49
heimdall/source/ReceiveFilePartPacket.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef RECEIVEFILEPARTPACKET_H
|
||||
#define RECEIVEFILEPARTPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "InboundPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class ReceiveFilePartPacket : public InboundPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = 500
|
||||
};
|
||||
|
||||
ReceiveFilePartPacket() : InboundPacket(kDataSize, true)
|
||||
{
|
||||
}
|
||||
|
||||
bool Unpack(void)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
79
heimdall/source/ResponsePacket.h
Normal file
79
heimdall/source/ResponsePacket.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef RESPONSEPACKET_H
|
||||
#define RESPONSEPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "InboundPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class ResponsePacket : public InboundPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kResponseTypeSendFilePart = 0x00,
|
||||
kResponseTypeSessionSetup = 0x64,
|
||||
kResponseTypePitFile = 0x65,
|
||||
kResponseTypeFileTransfer = 0x66,
|
||||
kResponseTypeEndSession = 0x67
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int responseType;
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = 4
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
ResponsePacket(int responseType) : InboundPacket(8)
|
||||
{
|
||||
this->responseType = responseType;
|
||||
}
|
||||
|
||||
unsigned int GetResponseType(void) const
|
||||
{
|
||||
return (responseType);
|
||||
}
|
||||
|
||||
virtual bool Unpack(void)
|
||||
{
|
||||
unsigned int receivedResponseType = UnpackInteger(0);
|
||||
if (receivedResponseType != responseType)
|
||||
{
|
||||
responseType = receivedResponseType;
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
63
heimdall/source/SendFilePartPacket.h
Normal file
63
heimdall/source/SendFilePartPacket.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef SENDFILEPARTPACKET_H
|
||||
#define SENDFILEPARTPACKET_H
|
||||
|
||||
// C Standard Library
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// Heimdall
|
||||
#include "Packet.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class SendFilePartPacket : public OutboundPacket
|
||||
{
|
||||
public:
|
||||
|
||||
SendFilePartPacket(FILE *file, unsigned int size) : OutboundPacket(size)
|
||||
{
|
||||
memset(data, 0, size);
|
||||
|
||||
unsigned int position = (unsigned int)FileTell(file);
|
||||
|
||||
FileSeek(file, 0, SEEK_END);
|
||||
unsigned int fileSize = (unsigned int)FileTell(file);
|
||||
FileSeek(file, position, SEEK_SET);
|
||||
|
||||
// min(fileSize, size)
|
||||
unsigned int bytesToRead = (fileSize < size) ? fileSize - position : size;
|
||||
(void)fread(data, 1, bytesToRead, file);
|
||||
}
|
||||
|
||||
SendFilePartPacket(unsigned char *buffer, unsigned int size) : OutboundPacket(size)
|
||||
{
|
||||
memcpy(data, buffer, size);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
58
heimdall/source/SendFilePartResponse.h
Normal file
58
heimdall/source/SendFilePartResponse.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef SENDFILEPARTRESPONSE_H
|
||||
#define SENDFILEPARTRESPONSE_H
|
||||
|
||||
// Heimdall
|
||||
#include "ResponsePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class SendFilePartResponse : public ResponsePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int partIndex;
|
||||
|
||||
public:
|
||||
|
||||
SendFilePartResponse() : ResponsePacket(ResponsePacket::kResponseTypeSendFilePart)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int GetPartIndex(void) const
|
||||
{
|
||||
return (partIndex);
|
||||
}
|
||||
|
||||
bool Unpack(void)
|
||||
{
|
||||
if (!ResponsePacket::Unpack())
|
||||
return (false);
|
||||
|
||||
partIndex = UnpackInteger(ResponsePacket::kDataSize);
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
75
heimdall/source/SessionSetupPacket.h
Normal file
75
heimdall/source/SessionSetupPacket.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef SESSIONSETUPPACKET_H
|
||||
#define SESSIONSETUPPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "ControlPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class SessionSetupPacket : public ControlPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kBeginSession = 0,
|
||||
kDeviceType = 1, // ?
|
||||
kTotalBytes = 2,
|
||||
//kEnableSomeSortOfFlag = 3,
|
||||
kFilePartSize = 5,
|
||||
kEnableTFlash = 8
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int request;
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = ControlPacket::kDataSize + 4
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
SessionSetupPacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypeSession)
|
||||
{
|
||||
this->request = request;
|
||||
}
|
||||
|
||||
unsigned int GetRequest(void) const
|
||||
{
|
||||
return (request);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
ControlPacket::Pack();
|
||||
|
||||
PackInteger(ControlPacket::kDataSize, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
58
heimdall/source/SessionSetupResponse.h
Normal file
58
heimdall/source/SessionSetupResponse.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef SESSIONSETUPRESPONSE_H
|
||||
#define SESSIONSETUPRESPONSE_H
|
||||
|
||||
// Heimdall
|
||||
#include "ResponsePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class SessionSetupResponse : public ResponsePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int result;
|
||||
|
||||
public:
|
||||
|
||||
SessionSetupResponse() : ResponsePacket(ResponsePacket::kResponseTypeSessionSetup)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int GetResult(void) const
|
||||
{
|
||||
return (result);
|
||||
}
|
||||
|
||||
bool Unpack(void)
|
||||
{
|
||||
if (!ResponsePacket::Unpack())
|
||||
return (false);
|
||||
|
||||
result = UnpackInteger(ResponsePacket::kDataSize);
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
74
heimdall/source/SetupSessionPacket.h
Normal file
74
heimdall/source/SetupSessionPacket.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* Copyright (c) 2010-2012 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef SETUPSESSIONPACKET_H
|
||||
#define SETUPSESSIONPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "ControlPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class SetupSessionPacket : public ControlPacket
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kBeginSession = 0,
|
||||
kDeviceInfo = 1,
|
||||
kTotalBytes = 2
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int request;
|
||||
unsigned int unknown3Parameter;
|
||||
|
||||
public:
|
||||
|
||||
SetupSessionPacket(unsigned int request, unsigned int unknown3Parameter = 0)
|
||||
: ControlPacket(ControlPacket::kControlTypeSetupSession)
|
||||
{
|
||||
this->request = request;
|
||||
this->unknown3Parameter = unknown3Parameter;
|
||||
}
|
||||
|
||||
unsigned int GetRequest(void) const
|
||||
{
|
||||
return (request);
|
||||
}
|
||||
|
||||
unsigned int GetUnknown3Parameter(void) const
|
||||
{
|
||||
return (unknown3Parameter);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
ControlPacket::Pack();
|
||||
|
||||
PackInteger(ControlPacket::kDataSize, request);
|
||||
PackInteger(ControlPacket::kDataSize + 4, unknown3Parameter);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
58
heimdall/source/SetupSessionResponse.h
Normal file
58
heimdall/source/SetupSessionResponse.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2010-2012 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef SETUPSESSIONRESPONSE_H
|
||||
#define SETUPSESSIONRESPONSE_H
|
||||
|
||||
// Heimdall
|
||||
#include "ResponsePacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class SetupSessionResponse : public ResponsePacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int unknown;
|
||||
|
||||
public:
|
||||
|
||||
SetupSessionResponse() : ResponsePacket(ResponsePacket::kResponseTypeBeginSession)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int GetUnknown(void) const
|
||||
{
|
||||
return (unknown);
|
||||
}
|
||||
|
||||
bool Unpack(void)
|
||||
{
|
||||
if (!ResponsePacket::Unpack())
|
||||
return (false);
|
||||
|
||||
unknown = UnpackInteger(ResponsePacket::kDataSize);
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
56
heimdall/source/TotalBytesPacket.h
Normal file
56
heimdall/source/TotalBytesPacket.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef TOTALBYTESPACKET_H
|
||||
#define TOTALBYTESPACKET_H
|
||||
|
||||
// Heimdall
|
||||
#include "SessionSetupPacket.h"
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
class TotalBytesPacket : public SessionSetupPacket
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned int totalBytes;
|
||||
|
||||
public:
|
||||
|
||||
TotalBytesPacket(unsigned int totalBytes) : SessionSetupPacket(SessionSetupPacket::kTotalBytes)
|
||||
{
|
||||
this->totalBytes = totalBytes;
|
||||
}
|
||||
|
||||
unsigned int GetTotalBytes(void) const
|
||||
{
|
||||
return (totalBytes);
|
||||
}
|
||||
|
||||
void Pack(void)
|
||||
{
|
||||
SessionSetupPacket::Pack();
|
||||
|
||||
PackInteger(SessionSetupPacket::kDataSize, totalBytes);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
82
heimdall/source/Utility.cpp
Normal file
82
heimdall/source/Utility.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <cerrno>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
#include "Utility.h"
|
||||
|
||||
using namespace Heimdall;
|
||||
|
||||
NumberParsingStatus Utility::ParseInt(int &intValue, const char *string, int base)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
char *end;
|
||||
long longValue = strtol(string, &end, base);
|
||||
|
||||
if (*string == '\0' || *end != '\0')
|
||||
{
|
||||
return (kNumberParsingStatusInconvertible);
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
{
|
||||
intValue = (longValue == LONG_MAX) ? INT_MAX : INT_MIN;
|
||||
return (kNumberParsingStatusRangeError);
|
||||
}
|
||||
else if (longValue > INT_MAX)
|
||||
{
|
||||
intValue = INT_MAX;
|
||||
return (kNumberParsingStatusRangeError);
|
||||
}
|
||||
else if (longValue < INT_MIN)
|
||||
{
|
||||
intValue = INT_MIN;
|
||||
return (kNumberParsingStatusRangeError);
|
||||
}
|
||||
|
||||
intValue = longValue;
|
||||
return (kNumberParsingStatusSuccess);
|
||||
}
|
||||
|
||||
NumberParsingStatus Utility::ParseUnsignedInt(unsigned int &uintValue, const char *string, int base)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
char *end;
|
||||
unsigned long ulongValue = strtoul(string, &end, base);
|
||||
|
||||
if (*string == '\0' || *end != '\0')
|
||||
{
|
||||
return kNumberParsingStatusInconvertible;
|
||||
}
|
||||
else if (errno == ERANGE || ulongValue > INT_MAX)
|
||||
{
|
||||
uintValue = UINT_MAX;
|
||||
return (kNumberParsingStatusRangeError);
|
||||
}
|
||||
|
||||
uintValue = ulongValue;
|
||||
return (kNumberParsingStatusSuccess);
|
||||
}
|
40
heimdall/source/Utility.h
Normal file
40
heimdall/source/Utility.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef UTILITY_H
|
||||
#define UTILITY_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
kNumberParsingStatusSuccess = 0,
|
||||
kNumberParsingStatusRangeError,
|
||||
kNumberParsingStatusInconvertible
|
||||
} NumberParsingStatus;
|
||||
|
||||
namespace Utility
|
||||
{
|
||||
NumberParsingStatus ParseInt(int &intValue, const char *string, int base = 0);
|
||||
NumberParsingStatus ParseUnsignedInt(unsigned int &uintValue, const char *string, int base = 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
35
heimdall/source/VersionAction.cpp
Normal file
35
heimdall/source/VersionAction.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
#include "Interface.h"
|
||||
#include "VersionAction.h"
|
||||
|
||||
using namespace Heimdall;
|
||||
|
||||
const char *VersionAction::usage = "Action: version\n\
|
||||
Description: Displays the version number of this binary.\n";
|
||||
|
||||
int VersionAction::Execute(int argc, char **argv)
|
||||
{
|
||||
Interface::PrintVersion();
|
||||
return (0);
|
||||
}
|
34
heimdall/source/VersionAction.h
Normal file
34
heimdall/source/VersionAction.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef VERSIONACTION_H
|
||||
#define VERSIONACTION_H
|
||||
|
||||
namespace Heimdall
|
||||
{
|
||||
namespace VersionAction
|
||||
{
|
||||
extern const char *usage;
|
||||
|
||||
int Execute(int argc, char **argv);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
55
heimdall/source/main.cpp
Normal file
55
heimdall/source/main.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
// libpit
|
||||
#include "libpit.h"
|
||||
|
||||
// Heimdall
|
||||
#include "Heimdall.h"
|
||||
#include "HelpAction.h"
|
||||
#include "Interface.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Heimdall;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
Interface::PrintUsage();
|
||||
return (0);
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
map<string, Interface::ActionInfo>::const_iterator actionIt = Interface::GetActionMap().find(argv[1]);
|
||||
|
||||
if (actionIt != Interface::GetActionMap().end())
|
||||
result = actionIt->second.executeFunction(argc, argv);
|
||||
else
|
||||
result = HelpAction::Execute(argc, argv);
|
||||
|
||||
return (result);
|
||||
}
|
9
libpit/CMakeLists.txt
Normal file
9
libpit/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
cmake_minimum_required(VERSION 2.8.4)
|
||||
project(libpit)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
|
||||
|
||||
set(LIBPIT_SOURCE_FILES
|
||||
source/libpit.cpp)
|
||||
|
||||
add_library(pit STATIC ${LIBPIT_SOURCE_FILES})
|
296
libpit/source/libpit.cpp
Normal file
296
libpit/source/libpit.cpp
Normal file
|
@ -0,0 +1,296 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
// libpit
|
||||
#include "libpit.h"
|
||||
|
||||
using namespace libpit;
|
||||
|
||||
PitEntry::PitEntry()
|
||||
{
|
||||
binaryType = false;
|
||||
deviceType = 0;
|
||||
identifier = 0;
|
||||
attributes = 0;
|
||||
updateAttributes = 0;
|
||||
blockSizeOrOffset = 0;
|
||||
blockCount = 0;
|
||||
fileOffset = 0;
|
||||
fileSize = 0;
|
||||
|
||||
memset(partitionName, 0, PitEntry::kPartitionNameMaxLength);
|
||||
memset(flashFilename, 0, PitEntry::kFlashFilenameMaxLength);
|
||||
memset(fotaFilename, 0, PitEntry::kFotaFilenameMaxLength);
|
||||
}
|
||||
|
||||
PitEntry::~PitEntry()
|
||||
{
|
||||
}
|
||||
|
||||
bool PitEntry::Matches(const PitEntry *otherPitEntry) const
|
||||
{
|
||||
if (binaryType == otherPitEntry->binaryType && deviceType == otherPitEntry->deviceType && identifier == otherPitEntry->identifier
|
||||
&& attributes == otherPitEntry->attributes && updateAttributes == otherPitEntry->updateAttributes && blockSizeOrOffset == otherPitEntry->blockSizeOrOffset
|
||||
&& blockCount == otherPitEntry->blockCount && fileOffset == otherPitEntry->fileOffset && fileSize == otherPitEntry->fileSize
|
||||
&& strcmp(partitionName, otherPitEntry->partitionName) == 0 && strcmp(flashFilename, otherPitEntry->flashFilename) == 0
|
||||
&& strcmp(fotaFilename, otherPitEntry->fotaFilename) == 0)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PitData::PitData()
|
||||
{
|
||||
entryCount = 0;
|
||||
|
||||
unknown1 = 0;
|
||||
unknown2 = 0;
|
||||
|
||||
unknown3 = 0;
|
||||
unknown4 = 0;
|
||||
|
||||
unknown5 = 0;
|
||||
unknown6 = 0;
|
||||
|
||||
unknown7 = 0;
|
||||
unknown8 = 0;
|
||||
}
|
||||
|
||||
PitData::~PitData()
|
||||
{
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
delete entries[i];
|
||||
}
|
||||
|
||||
bool PitData::Unpack(const unsigned char *data)
|
||||
{
|
||||
if (PitData::UnpackInteger(data, 0) != PitData::kFileIdentifier)
|
||||
return (false);
|
||||
|
||||
// Remove existing entries
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
delete entries[i];
|
||||
|
||||
entryCount = PitData::UnpackInteger(data, 4);
|
||||
|
||||
entries.resize(entryCount);
|
||||
|
||||
unknown1 = PitData::UnpackInteger(data, 8);
|
||||
unknown2 = PitData::UnpackInteger(data, 12);
|
||||
|
||||
unknown3 = PitData::UnpackShort(data, 16);
|
||||
unknown4 = PitData::UnpackShort(data, 18);
|
||||
|
||||
unknown5 = PitData::UnpackShort(data, 20);
|
||||
unknown6 = PitData::UnpackShort(data, 22);
|
||||
|
||||
unknown7 = PitData::UnpackShort(data, 24);
|
||||
unknown8 = PitData::UnpackShort(data, 26);
|
||||
|
||||
unsigned int integerValue;
|
||||
unsigned int entryOffset;
|
||||
|
||||
for (unsigned int i = 0; i < entryCount; i++)
|
||||
{
|
||||
entryOffset = PitData::kHeaderDataSize + i * PitEntry::kDataSize;
|
||||
|
||||
entries[i] = new PitEntry();
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset);
|
||||
entries[i]->SetBinaryType(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 4);
|
||||
entries[i]->SetDeviceType(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 8);
|
||||
entries[i]->SetIdentifier(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 12);
|
||||
entries[i]->SetAttributes(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 16);
|
||||
entries[i]->SetUpdateAttributes(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 20);
|
||||
entries[i]->SetBlockSizeOrOffset(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 24);
|
||||
entries[i]->SetBlockCount(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 28);
|
||||
entries[i]->SetFileOffset(integerValue);
|
||||
|
||||
integerValue = PitData::UnpackInteger(data, entryOffset + 32);
|
||||
entries[i]->SetFileSize(integerValue);
|
||||
|
||||
entries[i]->SetPartitionName((const char *)data + entryOffset + 36);
|
||||
entries[i]->SetFlashFilename((const char *)data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength);
|
||||
entries[i]->SetFotaFilename((const char *)data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength + PitEntry::kFlashFilenameMaxLength);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
void PitData::Pack(unsigned char *data) const
|
||||
{
|
||||
PitData::PackInteger(data, 0, PitData::kFileIdentifier);
|
||||
|
||||
PitData::PackInteger(data, 4, entryCount);
|
||||
|
||||
PitData::PackInteger(data, 8, unknown1);
|
||||
PitData::PackInteger(data, 12, unknown2);
|
||||
|
||||
PitData::PackShort(data, 16, unknown3);
|
||||
PitData::PackShort(data, 18, unknown4);
|
||||
|
||||
PitData::PackShort(data, 20, unknown5);
|
||||
PitData::PackShort(data, 22, unknown6);
|
||||
|
||||
PitData::PackShort(data, 24, unknown7);
|
||||
PitData::PackShort(data, 26, unknown8);
|
||||
|
||||
int entryOffset;
|
||||
|
||||
for (unsigned int i = 0; i < entryCount; i++)
|
||||
{
|
||||
entryOffset = PitData::kHeaderDataSize + i * PitEntry::kDataSize;
|
||||
|
||||
PitData::PackInteger(data, entryOffset, entries[i]->GetBinaryType());
|
||||
|
||||
PitData::PackInteger(data, entryOffset + 4, entries[i]->GetDeviceType());
|
||||
PitData::PackInteger(data, entryOffset + 8, entries[i]->GetIdentifier());
|
||||
PitData::PackInteger(data, entryOffset + 12, entries[i]->GetAttributes());
|
||||
|
||||
PitData::PackInteger(data, entryOffset + 16, entries[i]->GetUpdateAttributes());
|
||||
|
||||
PitData::PackInteger(data, entryOffset + 20, entries[i]->GetBlockSizeOrOffset());
|
||||
PitData::PackInteger(data, entryOffset + 24, entries[i]->GetBlockCount());
|
||||
|
||||
PitData::PackInteger(data, entryOffset + 28, entries[i]->GetFileOffset());
|
||||
PitData::PackInteger(data, entryOffset + 32, entries[i]->GetFileSize());
|
||||
|
||||
memcpy(data + entryOffset + 36, entries[i]->GetPartitionName(), PitEntry::kPartitionNameMaxLength);
|
||||
memcpy(data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength, entries[i]->GetFlashFilename(), PitEntry::kFlashFilenameMaxLength);
|
||||
memcpy(data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength + PitEntry::kFlashFilenameMaxLength,
|
||||
entries[i]->GetFotaFilename(), PitEntry::kFotaFilenameMaxLength);
|
||||
}
|
||||
}
|
||||
|
||||
bool PitData::Matches(const PitData *otherPitData) const
|
||||
{
|
||||
if (entryCount == otherPitData->entryCount && unknown1 == otherPitData->unknown1 && unknown2 == otherPitData->unknown2
|
||||
&& unknown3 == otherPitData->unknown3 && unknown4 == otherPitData->unknown4 && unknown5 == otherPitData->unknown5
|
||||
&& unknown6 == otherPitData->unknown6 && unknown7 == otherPitData->unknown7 && unknown8 == otherPitData->unknown8)
|
||||
{
|
||||
for (unsigned int i = 0; i < entryCount; i++)
|
||||
{
|
||||
if (!entries[i]->Matches(otherPitData->entries[i]))
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
void PitData::Clear(void)
|
||||
{
|
||||
entryCount = 0;
|
||||
|
||||
unknown1 = 0;
|
||||
unknown2 = 0;
|
||||
|
||||
unknown3 = 0;
|
||||
unknown4 = 0;
|
||||
|
||||
unknown5 = 0;
|
||||
unknown6 = 0;
|
||||
|
||||
unknown7 = 0;
|
||||
unknown8 = 0;
|
||||
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
delete entries[i];
|
||||
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
PitEntry *PitData::GetEntry(unsigned int index)
|
||||
{
|
||||
return (entries[index]);
|
||||
}
|
||||
|
||||
const PitEntry *PitData::GetEntry(unsigned int index) const
|
||||
{
|
||||
return (entries[index]);
|
||||
}
|
||||
|
||||
PitEntry *PitData::FindEntry(const char *partitionName)
|
||||
{
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
{
|
||||
if (entries[i]->IsFlashable() && strcmp(entries[i]->GetPartitionName(), partitionName) == 0)
|
||||
return (entries[i]);
|
||||
}
|
||||
|
||||
return (nullptr);
|
||||
}
|
||||
|
||||
const PitEntry *PitData::FindEntry(const char *partitionName) const
|
||||
{
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
{
|
||||
if (entries[i]->IsFlashable() && strcmp(entries[i]->GetPartitionName(), partitionName) == 0)
|
||||
return (entries[i]);
|
||||
}
|
||||
|
||||
return (nullptr);
|
||||
}
|
||||
|
||||
PitEntry *PitData::FindEntry(unsigned int partitionIdentifier)
|
||||
{
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
{
|
||||
if (entries[i]->IsFlashable() && entries[i]->GetIdentifier() == partitionIdentifier)
|
||||
return (entries[i]);
|
||||
}
|
||||
|
||||
return (nullptr);
|
||||
}
|
||||
|
||||
const PitEntry *PitData::FindEntry(unsigned int partitionIdentifier) const
|
||||
{
|
||||
for (unsigned int i = 0; i < entries.size(); i++)
|
||||
{
|
||||
if (entries[i]->IsFlashable() && entries[i]->GetIdentifier() == partitionIdentifier)
|
||||
return (entries[i]);
|
||||
}
|
||||
|
||||
return (nullptr);
|
||||
}
|
417
libpit/source/libpit.h
Normal file
417
libpit/source/libpit.h
Normal file
|
@ -0,0 +1,417 @@
|
|||
/* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifndef LIBPIT_H
|
||||
#define LIBPIT_H
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#if (!(defined _MSC_VER) || (_MSC_VER < 1700))
|
||||
|
||||
#ifndef nullptr
|
||||
#define nullptr 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// C/C++ Standard Library
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace libpit
|
||||
{
|
||||
class PitEntry
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = 132,
|
||||
kPartitionNameMaxLength = 32,
|
||||
kFlashFilenameMaxLength = 32,
|
||||
kFotaFilenameMaxLength = 32
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kBinaryTypeApplicationProcessor = 0,
|
||||
kBinaryTypeCommunicationProcessor = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kDeviceTypeOneNand = 0,
|
||||
kDeviceTypeFile, // FAT
|
||||
kDeviceTypeMMC,
|
||||
kDeviceTypeAll // ?
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kAttributeWrite = 1,
|
||||
kAttributeSTL = 1 << 1/*,
|
||||
kAttributeBML = 1 << 2*/ // ???
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kUpdateAttributeFota = 1,
|
||||
kUpdateAttributeSecure = 1 << 1
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int binaryType;
|
||||
unsigned int deviceType;
|
||||
unsigned int identifier;
|
||||
unsigned int attributes;
|
||||
unsigned int updateAttributes;
|
||||
|
||||
unsigned int blockSizeOrOffset;
|
||||
unsigned int blockCount;
|
||||
|
||||
unsigned int fileOffset; // Obsolete
|
||||
unsigned int fileSize; // Obsolete
|
||||
|
||||
char partitionName[kPartitionNameMaxLength];
|
||||
char flashFilename[kFlashFilenameMaxLength]; // USB flash filename
|
||||
char fotaFilename[kFotaFilenameMaxLength]; // Firmware over the air
|
||||
|
||||
public:
|
||||
|
||||
PitEntry();
|
||||
~PitEntry();
|
||||
|
||||
bool Matches(const PitEntry *otherPitEntry) const;
|
||||
|
||||
bool IsFlashable(void) const
|
||||
{
|
||||
return strlen(partitionName) != 0;
|
||||
}
|
||||
|
||||
unsigned int GetBinaryType(void) const
|
||||
{
|
||||
return binaryType;
|
||||
}
|
||||
|
||||
void SetBinaryType(unsigned int binaryType)
|
||||
{
|
||||
this->binaryType = binaryType;
|
||||
}
|
||||
|
||||
unsigned int GetDeviceType(void) const
|
||||
{
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
void SetDeviceType(unsigned int deviceType)
|
||||
{
|
||||
this->deviceType = deviceType;
|
||||
}
|
||||
|
||||
unsigned int GetIdentifier(void) const
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
void SetIdentifier(unsigned int identifier)
|
||||
{
|
||||
this->identifier = identifier;
|
||||
}
|
||||
|
||||
unsigned int GetAttributes(void) const
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
void SetAttributes(unsigned int attributes)
|
||||
{
|
||||
this->attributes = attributes;
|
||||
}
|
||||
|
||||
unsigned int GetUpdateAttributes(void) const
|
||||
{
|
||||
return updateAttributes;
|
||||
}
|
||||
|
||||
void SetUpdateAttributes(unsigned int updateAttributes)
|
||||
{
|
||||
this->updateAttributes = updateAttributes;
|
||||
}
|
||||
|
||||
// Different versions of Loke (secondary bootloaders) on different devices intepret this differently.
|
||||
unsigned int GetBlockSizeOrOffset(void) const
|
||||
{
|
||||
return blockSizeOrOffset;
|
||||
}
|
||||
|
||||
void SetBlockSizeOrOffset(unsigned int blockSizeOrOffset)
|
||||
{
|
||||
this->blockSizeOrOffset = blockSizeOrOffset;
|
||||
}
|
||||
|
||||
unsigned int GetBlockCount(void) const
|
||||
{
|
||||
return blockCount;
|
||||
}
|
||||
|
||||
void SetBlockCount(unsigned int blockCount)
|
||||
{
|
||||
this->blockCount = blockCount;
|
||||
}
|
||||
|
||||
unsigned int GetFileOffset(void) const
|
||||
{
|
||||
return fileOffset;
|
||||
}
|
||||
|
||||
void SetFileOffset(unsigned int fileOffset)
|
||||
{
|
||||
this->fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
unsigned int GetFileSize(void) const
|
||||
{
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
void SetFileSize(unsigned int fileSize)
|
||||
{
|
||||
this->fileSize = fileSize;
|
||||
}
|
||||
|
||||
const char *GetPartitionName(void) const
|
||||
{
|
||||
return partitionName;
|
||||
}
|
||||
|
||||
void SetPartitionName(const char *partitionName)
|
||||
{
|
||||
// This isn't strictly necessary but ensures no junk is left in our PIT file.
|
||||
memset(this->partitionName, 0, kPartitionNameMaxLength);
|
||||
|
||||
if (strlen(partitionName) < kPartitionNameMaxLength)
|
||||
strcpy(this->partitionName, partitionName);
|
||||
else
|
||||
memcpy(this->partitionName, partitionName, kPartitionNameMaxLength - 1);
|
||||
}
|
||||
|
||||
const char *GetFlashFilename(void) const
|
||||
{
|
||||
return flashFilename;
|
||||
}
|
||||
|
||||
void SetFlashFilename(const char *flashFilename)
|
||||
{
|
||||
// This isn't strictly necessary but ensures no junk is left in our PIT file.
|
||||
memset(this->flashFilename, 0, kFlashFilenameMaxLength);
|
||||
|
||||
if (strlen(partitionName) < kFlashFilenameMaxLength)
|
||||
strcpy(this->flashFilename, flashFilename);
|
||||
else
|
||||
memcpy(this->flashFilename, flashFilename, kFlashFilenameMaxLength - 1);
|
||||
}
|
||||
|
||||
const char *GetFotaFilename(void) const
|
||||
{
|
||||
return fotaFilename;
|
||||
}
|
||||
|
||||
void SetFotaFilename(const char *fotaFilename)
|
||||
{
|
||||
// This isn't strictly necessary but ensures no junk is left in our PIT file.
|
||||
memset(this->fotaFilename, 0, kFotaFilenameMaxLength);
|
||||
|
||||
if (strlen(partitionName) < kFotaFilenameMaxLength)
|
||||
strcpy(this->fotaFilename, fotaFilename);
|
||||
else
|
||||
memcpy(this->fotaFilename, fotaFilename, kFotaFilenameMaxLength - 1);
|
||||
}
|
||||
};
|
||||
|
||||
class PitData
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kFileIdentifier = 0x12349876,
|
||||
kHeaderDataSize = 28,
|
||||
kPaddedSizeMultiplicand = 4096
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
unsigned int entryCount; // 0x04
|
||||
unsigned int unknown1; // 0x08
|
||||
unsigned int unknown2; // 0x0C
|
||||
|
||||
unsigned short unknown3; // 0x10
|
||||
unsigned short unknown4; // 0x12
|
||||
|
||||
unsigned short unknown5; // 0x14
|
||||
unsigned short unknown6; // 0x16
|
||||
|
||||
unsigned short unknown7; // 0x18
|
||||
unsigned short unknown8; // 0x1A
|
||||
|
||||
// Entries start at 0x1C
|
||||
std::vector<PitEntry *> entries;
|
||||
|
||||
static int UnpackInteger(const unsigned char *data, unsigned int offset)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
int value = (data[offset] << 24) | (data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) | data[offset + 3];
|
||||
#else
|
||||
// Flip endianness
|
||||
int value = data[offset] | (data[offset + 1] << 8) |
|
||||
(data[offset + 2] << 16) | (data[offset + 3] << 24);
|
||||
#endif
|
||||
return (value);
|
||||
}
|
||||
|
||||
static int UnpackShort(const unsigned char *data, unsigned int offset)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
short value = (data[offset] << 8) | data[offset + 1];
|
||||
#else
|
||||
// Flip endianness
|
||||
short value = data[offset] | (data[offset + 1] << 8);
|
||||
#endif
|
||||
return (value);
|
||||
}
|
||||
|
||||
static void PackInteger(unsigned char *data, unsigned int offset, unsigned int value)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
data[offset] = (value & 0xFF000000) >> 24;
|
||||
data[offset + 1] = (value & 0x00FF0000) >> 16;
|
||||
data[offset + 2] = (value & 0x0000FF00) >> 8;
|
||||
data[offset + 3] = value & 0x000000FF;
|
||||
#else
|
||||
// Flip endianness
|
||||
data[offset] = value & 0x000000FF;
|
||||
data[offset + 1] = (value & 0x0000FF00) >> 8;
|
||||
data[offset + 2] = (value & 0x00FF0000) >> 16;
|
||||
data[offset + 3] = (value & 0xFF000000) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PackShort(unsigned char *data, unsigned int offset, unsigned short value)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
data[offset] = (value & 0xFF00) >> 8;
|
||||
data[offset + 1] = value & 0x00FF;
|
||||
#else
|
||||
// Flip endianness
|
||||
data[offset] = value & 0x00FF;
|
||||
data[offset + 1] = (value & 0xFF00) >> 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
PitData();
|
||||
~PitData();
|
||||
|
||||
bool Unpack(const unsigned char *data);
|
||||
void Pack(unsigned char *data) const;
|
||||
|
||||
bool Matches(const PitData *otherPitData) const;
|
||||
|
||||
void Clear(void);
|
||||
|
||||
PitEntry *GetEntry(unsigned int index);
|
||||
const PitEntry *GetEntry(unsigned int index) const;
|
||||
|
||||
PitEntry *FindEntry(const char *partitionName);
|
||||
const PitEntry *FindEntry(const char *partitionName) const;
|
||||
|
||||
PitEntry *FindEntry(unsigned int partitionIdentifier);
|
||||
const PitEntry *FindEntry(unsigned int partitionIdentifier) const;
|
||||
|
||||
unsigned int GetEntryCount(void) const
|
||||
{
|
||||
return entryCount;
|
||||
}
|
||||
|
||||
unsigned int GetDataSize(void) const
|
||||
{
|
||||
return PitData::kHeaderDataSize + entryCount * PitEntry::kDataSize;
|
||||
}
|
||||
|
||||
unsigned int GetPaddedSize(void) const
|
||||
{
|
||||
unsigned int dataSize = GetDataSize();
|
||||
unsigned int paddedSize = (dataSize / kPaddedSizeMultiplicand) * kPaddedSizeMultiplicand;
|
||||
|
||||
if (dataSize % kPaddedSizeMultiplicand != 0)
|
||||
paddedSize += kPaddedSizeMultiplicand;
|
||||
|
||||
return paddedSize;
|
||||
}
|
||||
|
||||
unsigned int GetUnknown1(void) const
|
||||
{
|
||||
return unknown1;
|
||||
}
|
||||
|
||||
unsigned int GetUnknown2(void) const
|
||||
{
|
||||
return unknown2;
|
||||
}
|
||||
|
||||
unsigned short GetUnknown3(void) const
|
||||
{
|
||||
return unknown3;
|
||||
}
|
||||
|
||||
unsigned short GetUnknown4(void) const
|
||||
{
|
||||
return unknown4;
|
||||
}
|
||||
|
||||
unsigned short GetUnknown5(void) const
|
||||
{
|
||||
return unknown5;
|
||||
}
|
||||
|
||||
unsigned short GetUnknown6(void) const
|
||||
{
|
||||
return unknown6;
|
||||
}
|
||||
|
||||
unsigned short GetUnknown7(void) const
|
||||
{
|
||||
return unknown7;
|
||||
}
|
||||
|
||||
unsigned short GetUnknown8(void) const
|
||||
{
|
||||
return unknown8;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue