Exemple #1
0
/****************************************************************************
 * get_lbtable
 *
 * Find the coreboot table and set global variable lbtable to point to it.
 ****************************************************************************/
void get_lbtable(void)
{
	int i, bad_header_count, bad_table_count, bad_headers, bad_tables;

	if (lbtable != NULL)
		return;

	/* The coreboot table is located in low physical memory, which may be
	 * conveniently accessed by calling mmap() on /dev/mem.
	 */

	if ((fd = open("/dev/mem", O_RDONLY, 0)) < 0) {
		fprintf(stderr, "%s: Can not open /dev/mem for reading: %s\n",
			prog_name, strerror(errno));
		exit(1);
	}

	if ((low_phys_mem =
	     mmap(NULL, BYTES_TO_MAP, PROT_READ, MAP_SHARED, fd, 0))
	    == MAP_FAILED) {
		fprintf(stderr, "%s: Failed to mmap /dev/mem: %s\n", prog_name,
			strerror(errno));
		exit(1);
	}

	bad_header_count = 0;
	bad_table_count = 0;

	for (i = 0; i < NUM_MEM_RANGES; i++) {
		lbtable = lbtable_scan(phystov(mem_ranges[i].start),
				       phystov(mem_ranges[i].end),
				       &bad_headers, &bad_tables);

		if (lbtable != NULL)
			return;	/* success: we found it! */

		bad_header_count += bad_headers;
		bad_table_count += bad_tables;
	}

	fprintf(stderr,
		"%s: coreboot table not found.  coreboot does not appear to\n"
		"        be installed on this system.  Scanning for the table "
		"produced the\n"
		"        following results:\n\n"
		"            %d valid signatures were found with bad header "
		"checksums.\n"
		"            %d valid headers were found with bad table "
		"checksums.\n", prog_name, bad_header_count, bad_table_count);
	exit(1);
}
Exemple #2
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;
}
Exemple #3
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;
}