/**************************************************************************** * get_cmos_checksum_info * * Get layout information for CMOS checksum. ****************************************************************************/ static void get_cmos_checksum_info(void) { const cmos_entry_t *e; struct cmos_checksum *checksum; cmos_checksum_layout_t layout; unsigned index, index2; checksum = (struct cmos_checksum *)next_cmos_rec((const struct lb_record *)first_cmos_table_enum(), LB_TAG_OPTION_CHECKSUM); if (checksum != NULL) { /* We are lucky. The coreboot table hints us to the checksum. * We might have to check the type field here though. */ layout.summed_area_start = checksum->range_start; layout.summed_area_end = checksum->range_end; layout.checksum_at = checksum->location; try_convert_checksum_layout(&layout); cmos_checksum_start = layout.summed_area_start; cmos_checksum_end = layout.summed_area_end; cmos_checksum_index = layout.checksum_at; return; } if ((e = find_cmos_entry(checksum_param_name)) == NULL) return; /* If we get here, we are unlucky. The CMOS option table contains the * location of the CMOS checksum. However, there is no information * regarding which bytes of the CMOS area the checksum is computed over. * Thus we have to hope our presets will be fine. */ if (e->bit % 8) { fprintf(stderr, "%s: Error: CMOS checksum is not byte-aligned.\n", prog_name); exit(1); } index = e->bit / 8; index2 = index + 1; /* The CMOS checksum occupies 16 bits. */ if (verify_cmos_byte_index(index) || verify_cmos_byte_index(index2)) { fprintf(stderr, "%s: Error: CMOS checksum location out of range.\n", prog_name); exit(1); } if (((index >= cmos_checksum_start) && (index <= cmos_checksum_end)) || (((index2) >= cmos_checksum_start) && ((index2) <= cmos_checksum_end))) { fprintf(stderr, "%s: Error: CMOS checksum overlaps checksummed area.\n", prog_name); exit(1); } cmos_checksum_index = index; }
/**************************************************************************** * checksum_layout_to_bytes * * On entry, '*layout' contains checksum-related layout information expressed * in bits. Perform sanity checking on the information and convert it from * bit positions to byte positions. Return OK on success or an error code if * a sanity check fails. ****************************************************************************/ int checksum_layout_to_bytes(cmos_checksum_layout_t * layout) { unsigned start, end, index; start = layout->summed_area_start; end = layout->summed_area_end; index = layout->checksum_at; if (start % 8) return LAYOUT_SUMMED_AREA_START_NOT_ALIGNED; if ((end % 8) != 7) return LAYOUT_SUMMED_AREA_END_NOT_ALIGNED; if (index % 8) return LAYOUT_CHECKSUM_LOCATION_NOT_ALIGNED; if (end <= start) return LAYOUT_INVALID_SUMMED_AREA; /* Convert bit positions to byte positions. */ start /= 8; end /= 8; /* equivalent to "end = ((end - 7) / 8)" */ index /= 8; if (verify_cmos_byte_index(start) || verify_cmos_byte_index(end)) return LAYOUT_SUMMED_AREA_OUT_OF_RANGE; if (verify_cmos_byte_index(index)) return LAYOUT_CHECKSUM_LOCATION_OUT_OF_RANGE; /* checksum occupies 16 bits */ if (areas_overlap(start, end - start + 1, index, index + 1)) return LAYOUT_CHECKSUM_OVERLAPS_SUMMED_AREA; layout->summed_area_start = start; layout->summed_area_end = end; layout->checksum_at = index; return OK; }
static unsigned char cmos_hal_read(unsigned index) { unsigned short port_0, port_1; assert(!verify_cmos_byte_index(index)); if (index < 128) { port_0 = 0x70; port_1 = 0x71; } else { port_0 = 0x72; port_1 = 0x73; } OUTB(index, port_0); return INB(port_1); }
static void cmos_hal_write(unsigned index, unsigned char value) { unsigned short port_0, port_1; assert(!verify_cmos_byte_index(index)); if (index < 128) { port_0 = 0x70; port_1 = 0x71; } else { port_0 = 0x72; port_1 = 0x73; } OUTB(index, port_0); OUTB(value, port_1); }