Calculate last missing checksum field in the eeprom

This commit is contained in:
ergo720 2018-03-31 22:12:36 +02:00
parent 29410562c0
commit 72ae997d3d
3 changed files with 43 additions and 9 deletions

View File

@ -46,12 +46,18 @@ namespace xboxkrnl
#include "Cxbx.h" // For DbgPrintf
#include "EmuEEPROM.h" // For EEPROMInfo, EEPROMInfos
#include "..\CxbxKrnl\Emu.h" // For EmuWarning
#include "..\..\src\devices\LED.h" // For SetLEDSequence
#include "..\CxbxKrnl\CxbxKrnl.h"
xboxkrnl::XBOX_EEPROM *EEPROM = nullptr; // Set using CxbxRestoreEEPROM()
// Default value (NA), overwritten with the actual content in the eeprom by CxbxRestoreEEPROM
xboxkrnl::ULONG XboxFactoryGameRegion = XC_GAME_REGION_NA;
// Default eeprom key (all zeros). Used to calculate the checksum of the eeprom header and to encrypt it if desired
UCHAR EepromKey[20] = { 0 };
const EEPROMInfo* EmuFindEEPROMInfo(xboxkrnl::XC_VALUE_INDEX index)
{
for (int i = 0; EEPROMInfos[i].index != XC_END_MARKER; i++)
@ -130,7 +136,9 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
}
}
// TODO : Make sure EEPROM.bin is at least 256 bytes in size - FileSeek(hFileEEPROM, EEPROM_SIZE, soFromBeginning);
// Make sure EEPROM.bin is at least 256 bytes in size
SetFilePointer(hFileEEPROM, 256, nullptr, FILE_BEGIN);
SetEndOfFile(hFileEEPROM);
HANDLE hFileMappingEEPROM = CreateFileMapping(
hFileEEPROM,
@ -145,6 +153,15 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
return nullptr;
}
LARGE_INTEGER len_li;
GetFileSizeEx(hFileEEPROM, &len_li);
unsigned int FileSize = len_li.u.LowPart;
if (FileSize != 256)
{
CxbxKrnlCleanup("CxbxRestoreEEPROM : EEPROM.bin file is not 256 bytes large!\n");
return nullptr;
}
// Map EEPROM.bin contents into memory :
pEEPROM = (xboxkrnl::XBOX_EEPROM *)MapViewOfFile(
hFileMappingEEPROM,
@ -161,8 +178,6 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
// so that users do not need to delete their EEPROM.bin from older versions
gen_section_CRCs(pEEPROM);
// TODO : Verify checksums
// Check for (and fix) invalid fields that were set by previous versions of Cxbx-Reloaded
// Without this, all users would have to delete their EEPROM.bin
// The issue was that the AV_FLAG_XXhz was set in the wrong field, we fix it by
@ -174,12 +189,6 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
pEEPROM->FactorySettings.AVRegion = AV_STANDARD_NTSC_M | AV_FLAGS_60Hz;
}
// Initialize XboxFactoryGameRegion from the value stored in the eeprom
/*const EEPROMInfo* info = EmuFindEEPROMInfo(xboxkrnl::XC_ENCRYPTED_SECTION);
if (info != nullptr) {
XboxFactoryGameRegion = (*((xboxkrnl::XBOX_ENCRYPTED_SETTINGS*)((PBYTE)pEEPROM + info->value_offset))).GameRegion;
}*/
if (NeedsInitialization)
{
memset(pEEPROM, 0, EEPROM_SIZE);
@ -207,5 +216,24 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
DbgPrintf("INIT: Loaded EEPROM.bin\n");
}
// Update the existing Checksum if it is all zeros. Without this, all users would have to delete their EEPROM.bin
UCHAR Checksum[20] = { 0 };
if (!memcmp(Checksum, pEEPROM->EncryptedSettings.Checksum, 20))
{
xboxkrnl::XcHMAC(EepromKey, 16, pEEPROM->EncryptedSettings.Confounder, 8, pEEPROM->EncryptedSettings.HDKey, 20,
pEEPROM->EncryptedSettings.Checksum);
}
else
{
// Verify the checksum of the eeprom header
xboxkrnl::XcHMAC(EepromKey, 16, pEEPROM->EncryptedSettings.Confounder, 8, pEEPROM->EncryptedSettings.HDKey, 20, Checksum);
if (memcmp(Checksum, pEEPROM->EncryptedSettings.Checksum, 20))
{
// The checksums do not match. Log this error and flash the LED (red, off, red, off)
EmuWarning("Stored and calculated checksums don't match: eeprom corrupted");
SetLEDSequence(0xA0);
}
}
return pEEPROM;
}

View File

@ -102,6 +102,8 @@ extern xboxkrnl::ULONG XboxFactoryGameRegion;
void gen_section_CRCs(xboxkrnl::XBOX_EEPROM*);
extern UCHAR EepromKey[20];
#if defined(__cplusplus)
}
#endif

View File

@ -600,6 +600,10 @@ XBSYSAPI EXPORTNUM(29) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExSaveNonVolatileSetti
void * value_addr = nullptr;
DWORD result_length;
// Don't allow writing to the eeprom encrypted area
if (ValueIndex == XC_ENCRYPTED_SECTION)
RETURN(STATUS_OBJECT_NAME_NOT_FOUND);
// handle eeprom write
if (g_bIsDebug || ValueIndex <= XC_MAX_OS || ValueIndex > XC_MAX_FACTORY)
{