#include "../../amBackupStructs.h" #include "../../maiBackupStructs.h" #include "_devices.h" #define EEPROM_DUMP L"dev/eeprom.bin" #include "../../sysconf.h" // 8192 x 8 (64kbit) of eeprom BYTE EEPROM_DATA[0x2000]; void eeprom_dump() { HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if (dump == INVALID_HANDLE_VALUE) { log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed: %03x", GetLastError()); return; } else { log_info("eeprom", "Wrote eeprom to %ls", EEPROM_DUMP); } _WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL); FlushFileBuffers(dump); _CloseHandle(dump); } void eeprom_restore() { HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (dump == INVALID_HANDLE_VALUE) { // Make the file, even though it'll probably be empty eeprom_dump(); return; } DWORD read; if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL)) log_error("eeprom", "failed to restore (%d)", GetLastError()); _CloseHandle(dump); } #define fix_crc(block) \ do { \ (block).m_Crc = amiCrc32RCalc(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \ } while (0) void set_eeprom_network_config() { AM_SYSDATAwH_NETWORK_ETH0 NetEth0 = { 0 }; NetEth0.m_Eth.m_Flag = 0; // TODO: Allow DHCP NetEth0.m_Eth.m_IpAddress = _byteswap_ulong(MiceConfig.network.ip_address); NetEth0.m_Eth.m_SubnetMask = _byteswap_ulong(MiceConfig.network.subnet_mask); NetEth0.m_Eth.m_Gateway = _byteswap_ulong(MiceConfig.network.gateway); NetEth0.m_Eth.m_PrimaryDns = _byteswap_ulong(MiceConfig.network.primary_dns); NetEth0.m_Eth.m_SecondaryDns = _byteswap_ulong(MiceConfig.network.secondary_dns); fix_crc(NetEth0); memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH0_REG], &NetEth0, sizeof NetEth0); memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH0_DUP], &NetEth0, sizeof NetEth0); // TODO: Does anything ever use ETH1? AM_SYSDATAwH_NETWORK_ETH1 NetEth1 = { 0 }; fix_crc(NetEth1); memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH1_REG], &NetEth1, sizeof NetEth1); memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH1_DUP], &NetEth1, sizeof NetEth1); } void set_eeprom_static_config() { AM_SYSDATAwH_STATIC Static = { .m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8), .m_Rental = MiceConfig.sysconf.rental, }; strcpy_s(Static.m_strSerialId, sizeof Static.m_strSerialId, MiceConfig.sysconf.serial); fix_crc(Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_REG], &Static, sizeof Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_DUP], &Static, sizeof Static); } void build_eeprom() { if (FileExists(EEPROM_DUMP)) { eeprom_restore(); // Our network and static config always gets priority set_eeprom_static_config(); set_eeprom_network_config(); eeprom_dump(); return; } log_info("eeprom", "Building default EEPROM file"); memset(EEPROM_DATA, 0xff, sizeof EEPROM_DATA); set_eeprom_static_config(); AM_SYSDATAwH_CREDIT Credit = { .m_Config = { .ServiceType = 1, .CreditRate = 1, .CoinRate = { 1, 1 }, .Cost = { 1, 1, 1, 1, 1, 1, 1, 1 }, }, }; fix_crc(Credit); memcpy(&EEPROM_DATA[AM_SYSDATAwH_CREDIT_REG], &Credit, sizeof Credit); memcpy(&EEPROM_DATA[AM_SYSDATAwH_CREDIT_DUP], &Credit, sizeof Credit); set_eeprom_network_config(); AM_SYSDATAwH_HISTORY History = { 0 }; // TODO: Game ID here should be configurable. History.m_GameId[0] = '-'; History.m_GameId[1] = '-'; History.m_GameId[2] = '-'; History.m_GameId[3] = '-'; History.m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8); fix_crc(History); memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_REG], &History, sizeof History); memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_DUP], &History, sizeof History); AM_SYSDATAwH_ALPB_CARD_ID CardInfo = { 0 }; fix_crc(CardInfo); memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_CARD_ID_REG] + (sizeof History), &CardInfo, sizeof CardInfo); memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_CARD_ID_DUP] + (sizeof History), &CardInfo, sizeof CardInfo); AM_SYSDATAwH_ALPB_COMPUTER_NAME CompuerName = { 0 }; fix_crc(CompuerName); memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_COMPUTER_NAME_REG], &CompuerName, sizeof CompuerName); memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_COMPUTER_NAME_DUP], &CompuerName, sizeof CompuerName); AM_SYSDATAwH_ALPB_DEV_CONFIG DevConfig = { 0 }; fix_crc(DevConfig); memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_DEV_CONFIG_REG], &DevConfig, sizeof DevConfig); memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_DEV_CONFIG_DUP], &DevConfig, sizeof DevConfig); eeprom_dump(); } void ensure_valid_eeprom() { static BOOL built = false; if (built) { eeprom_restore(); return; } build_eeprom(); built = true; } void eeprom_read(WORD addr, BYTE* data, BYTE length) { ensure_valid_eeprom(); if (addr >= sizeof EEPROM_DATA) return; if (length + addr > sizeof EEPROM_DATA) length = (sizeof EEPROM_DATA - addr) & 0xff; memcpy(data, &EEPROM_DATA[addr], length); } void eeprom_write(WORD addr, BYTE* data, BYTE length) { ensure_valid_eeprom(); if (addr >= sizeof EEPROM_DATA) return; if (length + addr > sizeof EEPROM_DATA) length = (sizeof EEPROM_DATA - addr) & 0xff; memcpy(&EEPROM_DATA[addr], data, length); eeprom_dump(); } BOOL smbus_AT24C64AN_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { switch (cmd) { case ICH9_CMD_BLOCK: { log_misc("eeprom", "write %d bytes at 0x%03x", dlen, code); eeprom_write(code, data, dlen); return TRUE; } default: log_error("eeprom", "Unsupported write mode: %01x, %02x", cmd, code); return FALSE; } } BOOL smbus_AT24C64AN_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { switch (cmd) { case ICH9_CMD_BYTE: data[0] = 0x00; return TRUE; case ICH9_CMD_BLOCK: { log_misc("eeprom", "read %d bytes at 0x%03x", dlen, code); eeprom_read(code, data, dlen); return TRUE; } default: log_error("eeprom", "Unsupported read mode: %01x, %02x", cmd, code); return FALSE; } }