/* SPDX-License-Identifier: MIT * * Copyright (c) 2022-2026 Leah Rowe * * Functions related to GbE NVM checksums. * * Related file: word.c */ #ifdef __OpenBSD__ #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/common.h" void read_checksums(void) { struct xstate *x = xstatus(); struct commands *cmd; struct xfile *f; unsigned long _p; unsigned long _skip_part; unsigned char _num_invalid; unsigned char _max_invalid; cmd = &x->cmd[x->i]; f = &x->f; f->part_valid[0] = 0; f->part_valid[1] = 0; if (!cmd->chksum_read) return; _num_invalid = 0; _max_invalid = 2; if (cmd->arg_part) _max_invalid = 1; /* * Skip verification on this part, * but only when arg_part is set. */ _skip_part = f->part ^ 1; for (_p = 0; _p < 2; _p++) { /* * Only verify a part if it was *read* */ if (cmd->arg_part && (_p == _skip_part)) continue; f->part_valid[_p] = good_checksum(_p); if (!f->part_valid[_p]) ++_num_invalid; } if (_num_invalid >= _max_invalid) { if (_max_invalid == 1) err(ECANCELED, "%s: part %lu has a bad checksum", f->fname, (unsigned long)f->part); err(ECANCELED, "%s: No valid checksum found in file", f->fname); } } int good_checksum(unsigned long partnum) { unsigned short expected_checksum; unsigned short actual_checksum; expected_checksum = calculated_checksum(partnum); actual_checksum = nvm_word(NVM_CHECKSUM_WORD, partnum); if (expected_checksum == actual_checksum) { return 1; } else { return 0; } } void set_checksum(unsigned long p) { check_bin(p, "part number"); set_nvm_word(NVM_CHECKSUM_WORD, p, calculated_checksum(p)); } unsigned short calculated_checksum(unsigned long p) { unsigned long c; unsigned int val16; val16 = 0; for (c = 0; c < NVM_CHECKSUM_WORD; c++) val16 += (unsigned int)nvm_word(c, p); return (unsigned short)((NVM_CHECKSUM - val16) & 0xffff); }