Skip to content

Commit 0bf6f8b

Browse files
joevtdingusdev
authored andcommitted
romidentity: Add Old World ROM 64-bit checksum.
The 32-bit checksum of Old World ROMs only covers the first 3 MiB. Some Old World ROMs may have differences only in the last 1 MiB. Therefore, include the 64-bit checksum which covers all 4 MiB. Verify ROM size before trying to read from config_info.
1 parent 7aacd5c commit 0bf6f8b

3 files changed

Lines changed: 141 additions & 104 deletions

File tree

machines/machinefactory.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ static uint32_t oldworldchecksum(char *buf, size_t len) {
119119
return ck;
120120
}
121121

122-
bool MachineFactory::add(const string& machine_id, MachineDescription desc)
123-
{
122+
bool MachineFactory::add(const string& machine_id, MachineDescription desc) {
124123
if (get_registry().find(machine_id) != get_registry().end()) {
125124
return false;
126125
}
@@ -129,6 +128,15 @@ bool MachineFactory::add(const string& machine_id, MachineDescription desc)
129128
return true;
130129
}
131130

131+
static uint64_t oldworldchecksum64(char *buf, size_t len, size_t config_info_offset) {
132+
uint64_t ck = 0;
133+
for (size_t i = 0; i < len; i += 8, buf += 8) {
134+
if (i < config_info_offset || i >= config_info_offset + 40)
135+
ck += READ_QWORD_BE_A(buf);
136+
}
137+
return ck;
138+
}
139+
132140
void MachineFactory::list_machines()
133141
{
134142
cout << endl << "Supported machines:" << endl << endl;
@@ -330,6 +338,7 @@ string MachineFactory::machine_name_from_rom(char *rom_data, size_t rom_size) {
330338
uint32_t firmware_version = 0;
331339
uint32_t nw_product_id = 0;
332340
uint32_t ow_checksum_stored = 0; uint32_t ow_checksum_calculated = 0;
341+
uint64_t ow_checksum64_stored = 0; uint64_t ow_checksum64_calculated = 0;
333342
uint32_t nw_start_checksum_stored = 0; uint32_t nw_start_checksum_calculated = 0;
334343
uint32_t nw_config_checksum_stored = 0; uint32_t nw_config_checksum_calculated = 0;
335344
uint32_t nw_recovery_checksum_stored = 0; uint32_t nw_recovery_checksum_calculated = 0;
@@ -340,12 +349,15 @@ string MachineFactory::machine_name_from_rom(char *rom_data, size_t rom_size) {
340349
uint32_t nw_subconfig_checksum_calculated = 0;
341350

342351
char expected_ow[24];
352+
char expected_ow64[40];
343353
char expected_start[24];
344354
char expected_config[24];
345355
char expected_recovery[24];
346356
char expected_romimage[24];
347357
auto checksum_verbosity = loguru::Verbosity_INFO;
348-
expected_ow[0] = expected_start[0] = expected_config[0] = expected_recovery[0] = expected_romimage[0] = 0;
358+
auto checksum_verbosity2 = loguru::Verbosity_INFO;
359+
expected_ow[0] = expected_ow64[0] = 0;
360+
expected_start[0] = expected_config[0] = expected_recovery[0] = expected_romimage[0] = 0;
349361

350362
uint32_t config_info_offset;
351363
char rom_id_str[17];
@@ -413,13 +425,19 @@ string MachineFactory::machine_name_from_rom(char *rom_data, size_t rom_size) {
413425
if (rom_size >= 0x400000) {
414426
/* read ConfigInfo offset from file */
415427
config_info_offset = READ_DWORD_BE_A(&rom_data[0x300080]);
416-
417-
/* read ConfigInfo.BootstrapVersion field as C string */
418-
memcpy(rom_id_str, &rom_data[0x300064 + config_info_offset], 16);
419-
rom_id_str[16] = 0;
420-
for (int i = 0; i < 16; i++)
421-
if (rom_id_str[i] < ' ' || rom_id_str[i] > '~')
422-
rom_id_str[i] = '.';
428+
if (0x300000ULL + config_info_offset <= rom_size - 0x64 - 16) {
429+
ow_checksum64_calculated = oldworldchecksum64(&rom_data[0], rom_size, 0x300000 + config_info_offset);
430+
ow_checksum64_stored = READ_QWORD_BE_A(&rom_data[0x300020 + config_info_offset]);
431+
if (ow_checksum64_calculated != ow_checksum64_stored)
432+
snprintf(expected_ow64, sizeof(expected_ow64), " (expected 0x%016llx)", ow_checksum64_stored);
433+
434+
/* read ConfigInfo.BootstrapVersion field as C string */
435+
memcpy(rom_id_str, &rom_data[0x300064 + config_info_offset], 16);
436+
rom_id_str[16] = 0;
437+
for (int i = 0; i < 16; i++)
438+
if (rom_id_str[i] < ' ' || rom_id_str[i] > '~')
439+
rom_id_str[i] = '.';
440+
}
423441
}
424442
}
425443

@@ -436,6 +454,10 @@ string MachineFactory::machine_name_from_rom(char *rom_data, size_t rom_size) {
436454
&& info->ow_expected_checksum == ow_checksum_stored)
437455
+ (info->ow_expected_checksum
438456
&& info->ow_expected_checksum == ow_checksum_calculated)
457+
+ (info->ow_expected_checksum64
458+
&& info->ow_expected_checksum64 == ow_checksum64_stored)
459+
+ (info->ow_expected_checksum64
460+
&& info->ow_expected_checksum64 == ow_checksum64_calculated)
439461
+ (info->nw_subconfig_expected_checksum
440462
&& info->nw_subconfig_expected_checksum == nw_subconfig_checksum_calculated)
441463
+ (info->id_str && strcmp(rom_id_str, info->id_str) == 0)
@@ -544,8 +566,12 @@ string MachineFactory::machine_name_from_rom(char *rom_data, size_t rom_size) {
544566

545567
if (expected_ow[0] || expected_start[0] || expected_config[0] || expected_recovery[0] || expected_romimage[0])
546568
checksum_verbosity = loguru::Verbosity_ERROR;
569+
if (expected_ow64[0])
570+
checksum_verbosity2 = loguru::Verbosity_ERROR;
547571

548-
if (1 || print_all_info || checksum_verbosity != loguru::Verbosity_INFO) {
572+
if (print_all_info || checksum_verbosity != loguru::Verbosity_INFO ||
573+
checksum_verbosity2 != loguru::Verbosity_INFO
574+
) {
549575
if (is_nw) {
550576
if (has_nw_config) {
551577
VLOG_F(checksum_verbosity, " ROM Checksums: 0x%08x%s, 0x%08x%s, 0x%08x%s, 0x%08x%s",
@@ -567,6 +593,10 @@ string MachineFactory::machine_name_from_rom(char *rom_data, size_t rom_size) {
567593
VLOG_F(checksum_verbosity, " ROM Checksum: 0x%08x%s",
568594
ow_checksum_calculated, expected_ow
569595
);
596+
if (ow_checksum64_calculated || expected_ow64[0])
597+
VLOG_F(checksum_verbosity2, " ROM Checksum (64-bit): 0x%016llx%s",
598+
ow_checksum64_calculated, expected_ow64
599+
);
570600
}
571601
}
572602

0 commit comments

Comments
 (0)