Example #1
0
/****************************************************************************
 * get_layout_from_cmos_table
 *
 * Find the CMOS table which is stored within the coreboot table and set the
 * global variable cmos_table to point to it.
 ****************************************************************************/
void get_layout_from_cmos_table(void)
{
	get_lbtable();
	cmos_table = (const struct cmos_option_table *)
	    find_lbrec(LB_TAG_CMOS_OPTION_TABLE);
	process_layout();
}
Example #2
0
/****************************************************************************
 * 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 *)find_lbrec(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;
}
Example #3
0
/****************************************************************************
 * get_layout_from_cmos_table
 *
 * Find the CMOS table which is stored within the coreboot table and set the
 * global variable cmos_table to point to it.
 ****************************************************************************/
void get_layout_from_cmos_table(void)
{

	get_lbtable();
	cmos_table = (const struct cmos_option_table *)
	    find_lbrec(LB_TAG_CMOS_OPTION_TABLE);

	if ((cmos_table) == NULL) {
		fprintf(stderr,
			"%s: CMOS option table not found in coreboot table.  "
			"Apparently, the coreboot installed on this system was "
			"built without specifying CONFIG_HAVE_OPTION_TABLE.\n",
			prog_name);
		exit(1);
	}

	process_cmos_table();
	get_cmos_checksum_info();
}
Example #4
0
/****************************************************************************
 * list_lbtable_item
 *
 * Show the coreboot table item specified by 'item'.
 ****************************************************************************/
void list_lbtable_item(const char item[])
{
	int i;
	const struct lb_record *rec;

	for (i = 0; i < NUM_LBTABLE_CHOICES; i++) {
		if (strcmp(item, lbtable_choices[i].name) == 0)
			break;
	}

	if (i == NUM_LBTABLE_CHOICES) {
		fprintf(stderr, "%s: Invalid coreboot table item %s.\n",
			prog_name, item);
		exit(1);
	}

	if ((rec = find_lbrec(lbtable_choices[i].tag)) == NULL) {
		fprintf(stderr, lbtable_choices[i].nofound_msg, prog_name,
			lbtable_choices[i].name);
		exit(1);
	}

	lbtable_choices[i].print_fn(rec);
}
Example #5
0
/****************************************************************************
 * lbtable_scan
 *
 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot
 * table.  The first 4 bytes of the table are marked by the signature
 * { 'L', 'B', 'I', 'O' }.  'start' and 'end' indicate the addresses of the
 * first and last bytes of the chunk of memory to be scanned.  For instance,
 * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
 * chunk of memory starting at address 0x10000000.  'start' and 'end' are
 * physical addresses.
 *
 * If a coreboot table is found, return a pointer to it.  Otherwise return
 * NULL.  On return, *bad_header_count and *bad_table_count are set as
 * follows:
 *
 *     *bad_header_count:
 *         Indicates the number of times in which a valid signature was found
 *         but the header checksum was invalid.
 *
 *     *bad_table_count:
 *         Indicates the number of times in which a header with a valid
 *         checksum was found but the table checksum was invalid.
 ****************************************************************************/
static const struct lb_header *lbtable_scan(unsigned long start,
					    unsigned long end,
					    int *bad_header_count,
					    int *bad_table_count)
{
	static const char signature[4] = { 'L', 'B', 'I', 'O' };
	const struct lb_header *table;
	const struct lb_forward *forward;
	unsigned long p;
	uint32_t sig;

	assert(end >= start);
	memcpy(&sig, signature, sizeof(sig));
	table = NULL;
	*bad_header_count = 0;
	*bad_table_count = 0;

	/* Look for signature.  Table is aligned on 16-byte boundary.  Therefore
	 * only check every fourth 32-bit memory word.  As the loop is coded below,
	 * this function will behave in a reasonable manner for ALL possible values
	 * for 'start' and 'end': even weird boundary cases like 0x00000000 and
	 * 0xffffffff on a 32-bit architecture.
	 */
	map_pages(start, end - start);
	for (p = start;
	     (p <= end) &&
	     (end - p >= (sizeof(uint32_t) - 1)); p += 4) {
		if (*(uint32_t*)phystov(p) != sig)
			continue;

		/* We found a valid signature. */
		table = (const struct lb_header *)phystov(p);

		/* validate header checksum */
		if (compute_ip_checksum((void *)table, sizeof(*table))) {
			(*bad_header_count)++;
			continue;
		}

		map_pages(p, table->table_bytes + sizeof(*table));
		/* validate table checksum */
		if (table->table_checksum !=
		    compute_ip_checksum(((char *)table) + sizeof(*table),
					table->table_bytes)) {
			(*bad_table_count)++;
			continue;
		}

		/* checksums are ok: we found it! */
		/* But it may just be a forwarding table, so look if there's a forwarder */
		lbtable = table;
		forward = (struct lb_forward *)find_lbrec(LB_TAG_FORWARD);
		lbtable = NULL;

		if (forward) {
			uint64_t new_phys = forward->forward;
			table = lbtable_scan(new_phys, new_phys + getpagesize(),
					 bad_header_count, bad_table_count);
		}
		return table;
	}

	return NULL;
}
Example #6
0
/****************************************************************************
 * lbtable_scan
 *
 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot
 * table.  The first 4 bytes of the table are marked by the signature
 * { 'L', 'B', 'I', 'O' }.  'start' and 'end' indicate the addresses of the
 * first and last bytes of the chunk of memory to be scanned.  For instance,
 * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
 * chunk of memory starting at address 0x10000000.  'start' and 'end' are
 * virtual addresses in the address space of the current process.  They
 * represent a chunk of memory obtained by calling mmap() on /dev/mem.
 *
 * If a coreboot table is found, return a pointer to it.  Otherwise return
 * NULL.  On return, *bad_header_count and *bad_table_count are set as
 * follows:
 *
 *     *bad_header_count:
 *         Indicates the number of times in which a valid signature was found
 *         but the header checksum was invalid.
 *
 *     *bad_table_count:
 *         Indicates the number of times in which a header with a valid
 *         checksum was found but the table checksum was invalid.
 ****************************************************************************/
static const struct lb_header *lbtable_scan(unsigned long start,
					    unsigned long end,
					    int *bad_header_count,
					    int *bad_table_count)
{
	static const char signature[] = { 'L', 'B', 'I', 'O' };
	const struct lb_header *table;
	const struct lb_forward *forward;
	const uint32_t *p;
	uint32_t sig;

	assert(end >= start);
	sig = (*((const uint32_t *)signature));
	table = NULL;
	*bad_header_count = 0;
	*bad_table_count = 0;

	/* Look for signature.  Table is aligned on 16-byte boundary.  Therefore
	 * only check every fourth 32-bit memory word.  As the loop is coded below,
	 * this function will behave in a reasonable manner for ALL possible values
	 * for 'start' and 'end': even weird boundary cases like 0x00000000 and
	 * 0xffffffff on a 32-bit architecture.
	 */
	for (p = (const uint32_t *)start;
	     (((unsigned long)p) <= end) &&
	     ((end - (unsigned long)p) >= (sizeof(uint32_t) - 1)); p += 4) {
		if (*p != sig)
			continue;

		/* We found a valid signature. */
		table = (const struct lb_header *)p;

		/* validate header checksum */
		if (compute_ip_checksum((void *)table, sizeof(*table))) {
			(*bad_header_count)++;
			continue;
		}

		/* validate table checksum */
		if (table->table_checksum !=
		    compute_ip_checksum(((char *)table) + sizeof(*table),
					table->table_bytes)) {
			(*bad_table_count)++;
			continue;
		}

		/* checksums are ok: we found it! */
		/* But it may just be a forwarding table, so look if there's a forwarder */
		lbtable = table;
		forward = (struct lb_forward *)find_lbrec(LB_TAG_FORWARD);
		lbtable = NULL;

		if (forward) {
			uint64_t new_phys = forward->forward;

			new_phys &= ~(getpagesize() - 1);

			munmap((void *)low_phys_mem, BYTES_TO_MAP);
			if ((low_phys_mem =
			     mmap(NULL, BYTES_TO_MAP, PROT_READ, MAP_SHARED, fd,
				  (off_t) new_phys)) == MAP_FAILED) {
				fprintf(stderr,
					"%s: Failed to mmap /dev/mem: %s\n",
					prog_name, strerror(errno));
				exit(1);
			}
			low_phys_base = new_phys;
			table =
			    lbtable_scan(phystov(low_phys_base),
					 phystov(low_phys_base + BYTES_TO_MAP),
					 bad_header_count, bad_table_count);
		}
		return table;
	}

	return NULL;
}