Compare commits

...

16 Commits

Author SHA1 Message Date
Henrik Grimler 02b577ec77
v2.0.2
* Fix segfault when file to flash does not exist

* Rename some fields in the flashing protocol, MMC4096 seem to be UFS,
  and what I thought was the protocol number seem to be the number of
  logical units in the storage
2022-07-12 17:42:55 +02:00
Henrik Grimler 14f3521a6b
FlashAction: fix FileOpen check
Check needs to be right after it is opened, before we try to seek in
it.  Before this fix, heimdall segfaults if file does not exist.

Fixes commit 60ab9bbaff ("FlashAction: Make sure file fit partition
before flashing")
2022-07-12 17:23:21 +02:00
Henrik Grimler 0cf817a591
libpit: MMC4096 is really UFS
Change name to better describe the hardware.
2022-05-04 13:12:31 +02:00
Henrik Grimler c3516307d2
libpit: last number in PIT header is the "LUN count"
Where LUN probably stands for Logical Unit Number.  Previous
assumption that it was the odin protocol version was wrong, so let's
fix this.
2022-05-04 13:12:28 +02:00
Henrik Grimler f6c4698c8b
Revert "PIT: unknown version in PIT header has to be protocol version"
This assumption was wrong.  The number is really the number of logical
units in the storage, which tends to increase over time as the storage
space is increased I suppose.

This reverts commit e916c679ed.
2022-05-04 13:11:18 +02:00
Henrik Grimler d81e0f5bc2
v2.0.1
Except for general cleanup we have these functional changes:

* Change printed pit header: last unknown number seem to be the Odin
  protocol version.

* Only run libusb_reset_device on ubuntu: on some distros/devices
  resetting the device causes the handshake to fail (observered for
  degaswifi/SM-T230).
2022-02-13 11:38:55 +01:00
Henrik Grimler 62368adc7d
BridgeManager: only libusb_reset_device on ubuntu
It seems that only ubuntu needs libusb_reset_device for successful
handshake. On most distros and device it works with or without, but
for some devices (like degaswifi/SM-T230 with a Marvell PXA 1088 SOC)
it causes handshake to fail.

Probably libusb_reset_device causes issues only for some devices, but
there seem to be no way to distinguish which ones from Heimdall (not
based on Odin protocol version or SOC at least).

Fixes commit 07a14d4aa8 ("InitialiseProtocol: reset device before
handshake").
2022-02-13 11:17:22 +01:00
Henrik Grimler 0f1843c93c
BridgeManager: break another long line 2022-02-13 08:53:03 +01:00
Henrik Grimler 172ab65cbe
BridgeManager: use SetUsbLogLevel for setting usb log level 2022-02-13 08:53:00 +01:00
Henrik Grimler 1e7ff3b659
README: point to samsung-loki/samsung-docs for more docs 2022-01-01 20:38:27 +01:00
Henrik Grimler e916c679ed
PIT: unknown version in PIT header has to be protocol version
And in that case there now exists a fifth version of the Odin
protocol, seen on Galaxy S9 and newer.

In total we have seen these versions (as of January 2022):

* 0, on devices from around 2014 or older
* 3, on devices from around 2015
* 4, on devices from around 2016 - 2017
* 5, on devices from around 2018 or newer
2022-01-01 20:38:19 +01:00
Henrik Grimler e9a68f6862
BridgeManager: fix return value by libusb_get_device_list
And remove unnecessary spaces and break a long line.
2022-01-01 20:38:12 +01:00
Henrik Grimler 990ce68f5c
BridgeManager: fix missing newline in error messages 2021-12-31 00:16:46 +01:00
Antony Cherepanov c939ab18d1
Fix comparison between signed and unsigned integers
Warning was seen when compiling with -Wall.
2021-12-18 18:22:42 +01:00
Antony Cherepanov 1385b183d2
Packet destructor should be virtual
Fixes warning seen when compiling with -Wall.
2021-12-18 18:21:40 +01:00
Henrik Grimler 95e5c1cdcb
heimdall-frontend: set version to 2.0.0 here as well
Will not make a new release for just this though.
2021-12-16 17:40:42 +01:00
10 changed files with 84 additions and 81 deletions

View File

@ -53,3 +53,8 @@ refer to the appropriate platform specific README:
#### Windows
- Win32/README.txt ([online](Win32/README.txt))
### Odin protocol and PIT format
For more details on the Odin protocol, and the PIT files, see the
external project [samsung-loki/samsung-docs](https://samsung-loki.github.io/samsung-docs/).

View File

@ -114,7 +114,7 @@
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;">Version 2.0.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>

View File

@ -20,6 +20,7 @@
// C Standard Library
#include <cstdio>
#include <fstream>
// libusb
#include <libusb.h>
@ -80,16 +81,17 @@ int BridgeManager::FindDeviceInterface(void)
Interface::Print("Detecting device...\n");
struct libusb_device **devices;
int deviceCount = libusb_get_device_list(libusbContext, &devices);
unsigned int deviceCount = libusb_get_device_list(libusbContext, &devices);
for (int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
for (unsigned int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
{
libusb_device_descriptor descriptor;
libusb_get_device_descriptor(devices[deviceIndex], &descriptor);
for (int i = 0; i < BridgeManager::kSupportedDeviceCount; i++)
{
if (descriptor.idVendor == supportedDevices[i].vendorId && descriptor.idProduct == supportedDevices[i].productId)
if (descriptor.idVendor == supportedDevices[i].vendorId &&
descriptor.idProduct == supportedDevices[i].productId)
{
heimdallDevice = devices[deviceIndex];
libusb_ref_device(heimdallDevice);
@ -310,14 +312,20 @@ bool BridgeManager::InitialiseProtocol(void)
memcpy(dataBuffer, "ODIN", 4);
memset(dataBuffer + 4, 0, 1);
if (libusb_reset_device(deviceHandle))
#ifdef OS_LINUX
if (IsUbuntu())
{
Interface::PrintError("Failed to reset device!");
Interface::Print("Resetting device...\n");
if (libusb_reset_device(deviceHandle))
{
Interface::PrintError("Failed to reset device!\n");
}
}
#endif
if (!SendBulkTransfer(dataBuffer, 4, 1000))
{
Interface::PrintError("Failed to send handshake!");
Interface::PrintError("Failed to send handshake!\n");
}
// Expect "LOKE"
@ -407,29 +415,8 @@ bool BridgeManager::DetectDevice(void)
return (false);
}
// Setup libusb log level.
switch (usbLogLevel)
{
case UsbLogLevel::None:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
break;
case UsbLogLevel::Error:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_ERROR);
break;
case UsbLogLevel::Warning:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_WARNING);
break;
case UsbLogLevel::Info:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
break;
case UsbLogLevel::Debug:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
break;
}
// Set libusb log level.
SetUsbLogLevel(usbLogLevel);
// Get handle to Galaxy S device
struct libusb_device **devices;
@ -442,7 +429,8 @@ bool BridgeManager::DetectDevice(void)
for (int i = 0; i < BridgeManager::kSupportedDeviceCount; i++)
{
if (descriptor.idVendor == supportedDevices[i].vendorId && descriptor.idProduct == supportedDevices[i].productId)
if (descriptor.idVendor == supportedDevices[i].vendorId &&
descriptor.idProduct == supportedDevices[i].productId)
{
libusb_free_device_list(devices, deviceCount);
@ -468,33 +456,12 @@ int BridgeManager::Initialise(bool resume)
if (result != LIBUSB_SUCCESS)
{
Interface::PrintError("Failed to initialise libusb. libusb error: %d\n", result);
Interface::Print("Failed to connect to device!");
Interface::Print("Failed to connect to device!\n");
return (BridgeManager::kInitialiseFailed);
}
// Setup libusb log level.
switch (usbLogLevel)
{
case UsbLogLevel::None:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
break;
case UsbLogLevel::Error:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_ERROR);
break;
case UsbLogLevel::Warning:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_WARNING);
break;
case UsbLogLevel::Info:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
break;
case UsbLogLevel::Debug:
libusb_set_option(libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
break;
}
SetUsbLogLevel(usbLogLevel);
result = FindDeviceInterface();
@ -749,7 +716,7 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout, int emptyT
if (receivedSize < 0)
return (false);
if (receivedSize != packet->GetSize() && !packet->IsSizeVariable())
if (static_cast<unsigned int>(receivedSize) != packet->GetSize() && !packet->IsSizeVariable())
{
if (verbose)
Interface::PrintError("Incorrect packet size received - expected size = %d, received size = %d.\n", packet->GetSize(), receivedSize);
@ -1277,3 +1244,32 @@ void BridgeManager::SetUsbLogLevel(UsbLogLevel usbLogLevel)
}
}
}
#ifdef OS_LINUX
bool BridgeManager::IsUbuntu()
{
std::ifstream os_release("/etc/os-release");
std::string line, entry, os;
int pos;
while (std::getline(os_release, line))
{
pos = line.find("=");
entry = line.substr(0, pos);
if (entry == "ID")
{
os = line.substr(pos+1);
if (verbose)
{
Interface::Print("Linux distro ID: %s\n",
os.c_str());
}
if (os == "ubuntu")
{
return true;
}
break;
}
}
return false;
}
#endif

View File

@ -166,7 +166,9 @@ namespace Heimdall
bool SendFile(FILE *file, unsigned int destination, unsigned int deviceType, unsigned int fileIdentifier = 0xFFFFFFFF) const;
void SetUsbLogLevel(UsbLogLevel usbLogLevel);
#ifdef OS_LINUX
bool IsUbuntu(void);
#endif
UsbLogLevel GetUsbLogLevel(void) const
{
return usbLogLevel;

View File

@ -148,7 +148,7 @@ int DownloadPitAction::Execute(int argc, char **argv)
if (fileSize > 0)
{
if (fwrite(pitBuffer, 1, fileSize, outputPitFile) != fileSize)
if (fwrite(pitBuffer, 1, fileSize, outputPitFile) != static_cast<size_t>(fileSize))
{
Interface::PrintError("Failed to write PIT data to output file.\n");
success = false;

View File

@ -116,16 +116,16 @@ static bool openFiles(Arguments& arguments, vector<PartitionFile>& partitionFile
{
const StringArgument *stringArgument = static_cast<const StringArgument *>(*it);
FILE *file = FileOpen(stringArgument->GetValue().c_str(), "rb");
FileSeek(file, 0, SEEK_END);
unsigned long fileSize = (unsigned long)FileTell(file);
FileRewind(file);
if (!file)
{
Interface::PrintError("Failed to open file \"%s\"\n", stringArgument->GetValue().c_str());
return (false);
}
FileSeek(file, 0, SEEK_END);
unsigned long fileSize = (unsigned long)FileTell(file);
FileRewind(file);
partitionFiles.push_back(PartitionFile(argumentName.c_str(), file, fileSize));
}
}
@ -303,11 +303,11 @@ static bool flashPartitions(BridgeManager *bridgeManager, const vector<Partition
{
const PitEntry *part = pitData->FindEntry(it->argumentName);
if (part->GetDeviceType() != PitEntry::kDeviceTypeMMC &&
part->GetDeviceType() != PitEntry::kDeviceTypeMMC4096)
part->GetDeviceType() != PitEntry::kDeviceTypeUFS)
continue;
unsigned long partitionSize = part->GetBlockCount();
unsigned int blockSize = 512;
if (part->GetDeviceType() == PitEntry::kDeviceTypeMMC4096)
if (part->GetDeviceType() == PitEntry::kDeviceTypeUFS)
blockSize = 4096;
if (partitionSize > 0 && it->fileSize > partitionSize*blockSize)
{

View File

@ -42,7 +42,7 @@ using namespace Heimdall;
map<string, Interface::ActionInfo> actionMap;
bool stdoutErrors = false;
const char *version = "v2.0.0";
const char *version = "v2.0.2";
const char *actionUsage = "Usage: heimdall <action> <action arguments>\n";
const char *releaseInfo = "Heimdall %s\n\n\
@ -211,7 +211,7 @@ void Interface::PrintPit(const PitData *pitData)
Interface::Print("Entry Count: %d\n", pitData->GetEntryCount());
Interface::Print("Unknown string: %s\n", pitData->GetComTar2());
Interface::Print("CPU/bootloader tag: %s\n", pitData->GetCpuBlId());
Interface::Print("Version(?): 0x%04x\n", pitData->GetUnknown());
Interface::Print("Logic unit count: %d\n", pitData->GetLUCount());
for (unsigned int i = 0; i < pitData->GetEntryCount(); i++)
{
@ -257,8 +257,8 @@ void Interface::PrintPit(const PitData *pitData)
Interface::Print("All (?)");
break;
case PitEntry::kDeviceTypeMMC4096:
Interface::Print("MMC 4096");
case PitEntry::kDeviceTypeUFS:
Interface::Print("UFS");
break;
default:

View File

@ -45,7 +45,7 @@ namespace Heimdall
memset(data, 0, size);
}
~Packet()
virtual ~Packet()
{
delete [] data;
}

View File

@ -69,7 +69,7 @@ PitData::PitData()
com_tar2[0] = '\0';
cpu_bl_id[0] = '\0';
unknown_version = 0;
luCount = 0;
}
PitData::~PitData()
@ -98,7 +98,7 @@ bool PitData::Unpack(const unsigned char *data)
return (false);
cpu_bl_id[8]='\0';
unknown_version = PitData::UnpackShort(data, 24);
luCount = PitData::UnpackShort(data, 24);
unsigned int integerValue;
unsigned int entryOffset;
@ -153,7 +153,7 @@ void PitData::Pack(unsigned char *data) const
memcpy(&data[8], com_tar2, 8);
memcpy(&data[16], cpu_bl_id, 8);
PitData::PackShort(data, 24, unknown_version);
PitData::PackShort(data, 24, luCount);
int entryOffset;
@ -187,7 +187,7 @@ bool PitData::Matches(const PitData *otherPitData) const
if (entryCount == otherPitData->entryCount &&
(strncmp(com_tar2, otherPitData->com_tar2, 8) == 0) &&
(strncmp(cpu_bl_id, otherPitData->cpu_bl_id, 8) == 0) &&
unknown_version == otherPitData->unknown_version)
luCount == otherPitData->luCount)
{
for (unsigned int i = 0; i < entryCount; i++)
{
@ -211,7 +211,7 @@ void PitData::Clear(void)
cpu_bl_id[0] = '\0';
unknown_version = 0;
luCount = 0;
for (unsigned int i = 0; i < entries.size(); i++)
delete entries[i];

View File

@ -62,7 +62,7 @@ namespace libpit
kDeviceTypeFile, // FAT
kDeviceTypeMMC,
kDeviceTypeAll, // ?
kDeviceTypeMMC4096 = 8 // block size 4096
kDeviceTypeUFS = 8
};
enum
@ -261,12 +261,12 @@ namespace libpit
private:
unsigned int entryCount; // 0x04
char com_tar2[8+1]; // 0x08
unsigned int entryCount; // 0x04
char com_tar2[8+1]; // 0x08
char cpu_bl_id[8+1]; // 0x10
char cpu_bl_id[8+1]; // 0x10
unsigned short unknown_version; // 0x18
unsigned short luCount; // 0x18
// Entries start at 0x1C
std::vector<PitEntry *> entries;
@ -375,9 +375,9 @@ namespace libpit
return cpu_bl_id;
}
unsigned int GetUnknown(void) const
unsigned int GetLUCount(void) const
{
return unknown_version;
return luCount;
}
};
}