Exemple #1
0
/*
 *  fwts_low_mmap_walkdown()
 *	try to allocate a free space under the 2GB limit by
 *	walking down memory in CHUNK_SIZE steps for an unmapped region
 */
static void *fwts_low_mmap_walkdown(const size_t requested_size)
{
	void *addr;
	size_t page_size = fwts_page_size();
	size_t sz = (requested_size + page_size) & ~(page_size - 1);
	size_t pages = sz / page_size;
	unsigned char vec[pages];
	static void *last_addr = (void *)LIMIT_2GB;

	if (requested_size == 0)	/* Illegal */
		return MAP_FAILED;

	for (addr = last_addr - sz; addr > (void *)LIMIT_START; addr -= CHUNK_SIZE) {
		void *mapping;

		/* Already mapped? */
		if (mincore(addr, pages, vec) == 0)
			continue;

		/* Not mapped but mincore returned something unexpected? */
		if (errno != ENOMEM)
			continue;

		mapping = mmap(addr, requested_size, PROT_READ | PROT_WRITE,
			MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
		if (mapping != MAP_FAILED) {
			last_addr = mapping;
			return mapping;
		}
	}
	/* We've scanned all of memory, give up on subsequent calls */
	last_addr = (void *)LIMIT_START;

	return MAP_FAILED;
}
Exemple #2
0
/*
 *  fwts_munmap()
 *	Unmap memory mapped wuth fwts_mmap. Needs the mmap'd address and size.
 */
int fwts_munmap(void *mem, const size_t size)
{
	int page_size;
	off_t offset;

	page_size = fwts_page_size();
	offset = ((off_t)(mem)) & (page_size - 1);

	if (munmap((void *)((uint8_t *)mem - offset), size + offset) < 0)
		return FWTS_ERROR;

	return FWTS_OK;
}
Exemple #3
0
/*
 *  fwts_mmap()
 *	Try and map physical memory from offset address 'start' and length
 *	'size'. Return either the address or FWTS_MAP_FAILED if failed to mmap.
 */
void *fwts_mmap(const off_t start, const size_t size)
{
	int fd;
	int page_size;
	off_t offset;
	size_t length;
	void *mem;
	void *ret = FWTS_MAP_FAILED;

	page_size = fwts_page_size();
	offset = ((size_t)start) & (page_size - 1);
	length = (size_t)size + offset;

	if ((fd = open("/dev/mem", O_RDONLY)) < 0)
		return ret;

	if ((mem = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, start - offset)) != MAP_FAILED)
		ret = (void *)((uint8_t *)mem + offset);

	close(fd);

	return ret;
}
Exemple #4
0
static int compare_config_space(
	fwts_framework *fw,
	const fwts_acpi_mcfg_configuration *config)
{
	uint8_t *mapped_config_space;
	uint8_t config_space[16];
	size_t page_size, n;
	bool match;
	char path[PATH_MAX];
	FILE *fp;
	int i;

	page_size = fwts_page_size();

	/*
 	 * Sanity check on first config, this is enough to
	 * see if MMIO base is OK or not
	 */
	snprintf(path, sizeof(path),
		"/sys/bus/pci/devices/%4.4" PRIx16 ":00:00.0/config",
		config->pci_segment_group_number);

	if ((fp = fopen(path, "r")) == NULL) {
		fwts_log_warning(fw, "Could not open %s.", path);
		return FWTS_ERROR;
	}
	n = fread(config_space, 1, sizeof(config_space), fp);
	(void)fclose(fp);
	if (n != sizeof(config_space)) {
		fwts_log_warning(fw, "Could only read %zd bytes from %s, expecting %zd.", n, path, sizeof(config_space));
		return FWTS_ERROR;
	}

	if ((mapped_config_space = fwts_mmap(config->base_address, page_size)) == FWTS_MAP_FAILED) {
		fwts_log_error(fw, "Cannot mmap PCI config space at 0x%" PRIx64 ".",
			config->base_address);
		return FWTS_ERROR;
	}

	/* We only need to check if just the config space is readable */
	if (fwts_safe_memread(mapped_config_space, sizeof(config_space)) != FWTS_OK) {
		fwts_log_error(fw, "Cannot read PCI config space at 0x%" PRIx64 ".",
			config->base_address);
		(void)fwts_munmap(mapped_config_space, page_size);
		return FWTS_ERROR;
	}

	/*
	 * Need to explicitly do byte comparisons on region
	 * memcmp() fails as this can do 64 bit reads
	 */
	for (match = true, i = 0; i < 16; i++) {
		if (config_space[i] != mapped_config_space[i]) {
			match = false;
			break;
		}
	}
	(void)fwts_munmap(mapped_config_space, page_size);

	if (match)
		fwts_passed(fw, "PCI config space verified.");
	else
		fwts_failed(fw, LOG_LEVEL_MEDIUM,
			"PCIConfigSpaceBad",
			"PCI config space appears to not work.");

	return FWTS_OK;
}