In our EEPROMs we try to keep an eye on the contents since it is read by hardware.  At the same time, we don't want to increase initialization time too much so our scheme needed to balance protection with speed.  Basically we just sum together the first 63 16-bit words, ignoring any carries, and then subtract that result from 0xBABA.  That value goes into word 0x3F in the EEPROM. When validating the checksum, the first 64 words are added together and if the result is 0xBABA, the checksum is declared good. Here’s how the checksum word value is calculated in C:

u16 nvm_data;
u16 checksum = 0;

for (i = 0; i < 0x3F; i++) {
checksum += nvm_data;
}
checksum = 0xBABA – checksum;

After writing the value in checksum to word 0x3F, we have a valid checksum for the EEPROM. In assembly it’s more complex, mostly because of it being in assembly.

;
; zero word index counter and accumulator
;
xor     bx, bx
xor     cx, cx
UEC_Loop:
INVOKE  e1000_read_single_word, bx ; result in ax
inc     bx                 ; bump word index
cmp     bx, 03Fh           ; are we done?
jb      UEC_Loop           ; don't include the checksum word
;
; dropped out of loop - we've read first 63 words
;
mov     bx, 0BABAh
sub     bx, cx             ; proper checksum word value in bx

There are a couple of tricky parts when talking about this topic.  The first is, “Why 0xBABA?”  The second is, “What about 10-Gigabit EEPROMs?”

The first is easy to explain.  When the algorithm designers were working on it they needed a value that was not likely to appear in uninitialized EEPROMs.   Since it was to be in hex, the desire to make it "readable" was desired.    One of those engineers loves classic rock music, so he selected 0xBABA.   The second answer is a whole ’nother post!

Wrap up!

1)  Our EEPROM checksum scheme helps to keep our data intact by detecting unexpected content changes.

2)  It is a simple, time-tested scheme that doesn’t have too much overhead.

3)  Thanks for using Intel(R) Ethernet.