__sfr __at(0xff) POWEROFF; __sfr __at(0xfe) DEBUG; __sfr __at(0xfd) CHAROUT; __xdata __at(0xff00) unsigned char FLAG[0x100]; __sfr __at(0xfa) RAW_I2C_SCL; __sfr __at(0xfb) RAW_I2C_SDA; // I2C-M module/chip control data structure. __xdata __at(0xfe00) unsigned char I2C_ADDR; // 8-bit version. __xdata __at(0xfe01) unsigned char I2C_LENGTH; // At most 8 (excluding addr). __xdata __at(0xfe02) unsigned char I2C_RW_MASK; // 1 R, 0 W. __xdata __at(0xfe03) unsigned char I2C_ERROR_CODE; // 0 - no errors. __xdata __at(0xfe08) unsigned char I2C_DATA[8]; // Don't repeat addr. __sfr __at(0xfc) I2C_STATE; // Read: 0 - idle, 1 - busy; Write: 1 - start const unsigned int SEEPROM_I2C_ADDR_MEMORY = 0b10100000; const unsigned int SEEPROM_I2C_ADDR_SECURE = 0b01010000; void print(const char *str) { while (*str) { CHAROUT = *str++; } } void seeprom_wait_until_idle() { while (I2C_STATE != 0) {} } void seeprom_write_byte(unsigned char addr, unsigned char value) { seeprom_wait_until_idle(); I2C_ADDR = SEEPROM_I2C_ADDR_MEMORY; I2C_LENGTH = 2; I2C_ERROR_CODE = 0; I2C_DATA[0] = addr; I2C_DATA[1] = value; I2C_RW_MASK = 0b00; // 2x Write Byte I2C_STATE = 1; seeprom_wait_until_idle(); } unsigned char seeprom_read_byte(unsigned char addr) { seeprom_wait_until_idle(); I2C_ADDR = SEEPROM_I2C_ADDR_MEMORY; I2C_LENGTH = 2; I2C_ERROR_CODE = 0; I2C_DATA[0] = addr; I2C_RW_MASK = 0b10; // Write Byte, then Read Byte I2C_STATE = 1; seeprom_wait_until_idle(); if (I2C_ERROR_CODE != 0) { return 0x00; } return I2C_DATA[1]; } void seeprom_secure_banks(unsigned char mask) { seeprom_wait_until_idle(); I2C_ADDR = SEEPROM_I2C_ADDR_SECURE | (mask & 0b1111); I2C_LENGTH = 0; I2C_ERROR_CODE = 0; I2C_STATE = 1; seeprom_wait_until_idle(); } void secure_banks() { unsigned char i; print("[FW] Securing SecureEEPROM flag banks..........."); seeprom_secure_banks(0b0010); // Secure 64-byte bank with the flag. // Verify that the flag can NOT be read. for (i = 0; FLAG[i] != '\0'; i++) { if (seeprom_read_byte(64 + i) == FLAG[i]) { print("VERIFY FAIL\n"); POWEROFF = 1; } } print("DONE\n"); } void print_hex_digit(unsigned char c) { if (c >= 10) { CHAROUT = 'a' + (c - 10); } else { CHAROUT = '0' + c; } } void print_hex(unsigned char c) { print_hex_digit((c >> 4) & 0xf); print_hex_digit(c & 0xf); } void sda_low() { RAW_I2C_SDA = 0; } void sda_high() { RAW_I2C_SDA = 1; } void scl_low() { RAW_I2C_SCL = 0; } void scl_high() { RAW_I2C_SCL = 1; } void scl_cycle() { scl_high(); scl_low(); } char sda_read() { return RAW_I2C_SDA; } void start() { scl_high(); sda_high(); sda_low(); scl_low(); } void end() { sda_low(); scl_high(); sda_high(); } void send_bit(char b) { RAW_I2C_SDA = !!b; scl_cycle(); } char read_bit() { sda_high(); scl_high(); char r = !!RAW_I2C_SDA; scl_low(); return r; } char send_byte(char b) { for (int i = 7; i >= 0; i--) { send_bit((b >> i) & 1); } if (read_bit()) { print("NACK on "); print_hex(b); print("\n"); return 0; } return 1; } unsigned char read_byte() { unsigned char r = 0; for (int i = 0; i < 8; i++) { r = (r << 1) | read_bit(); } send_bit(1); return r; } void main(void) { //seeprom_write_byte(62, 'b'); RAW_I2C_SDA = 1; RAW_I2C_SCL = 1; start(); send_byte(SEEPROM_I2C_ADDR_MEMORY); send_byte(62); //end(); start(); send_byte(SEEPROM_I2C_ADDR_SECURE | 0b1111); start(); send_byte(SEEPROM_I2C_ADDR_MEMORY | 1); for (int i = 0; i < 80; i++) { print_hex(read_byte()); } end(); POWEROFF = 1; }