예제 #1
0
파일: oslinuxtbl.c 프로젝트: 020gzh/linux
static acpi_status osl_load_rsdp(void)
{
	struct acpi_table_header *mapped_table;
	u8 *rsdp_address;
	acpi_physical_address rsdp_base;
	acpi_size rsdp_size;

	/* Get RSDP from memory */

	rsdp_size = sizeof(struct acpi_table_rsdp);
	if (gbl_rsdp_base) {
		rsdp_base = gbl_rsdp_base;
	} else {
		rsdp_base = osl_find_rsdp_via_efi();
	}

	if (!rsdp_base) {
		rsdp_base = ACPI_HI_RSDP_WINDOW_BASE;
		rsdp_size = ACPI_HI_RSDP_WINDOW_SIZE;
	}

	rsdp_address = acpi_os_map_memory(rsdp_base, rsdp_size);
	if (!rsdp_address) {
		return (osl_get_last_status(AE_BAD_ADDRESS));
	}

	/* Search low memory for the RSDP */

	mapped_table = ACPI_CAST_PTR(struct acpi_table_header,
				     acpi_tb_scan_memory_for_rsdp(rsdp_address,
								  rsdp_size));
	if (!mapped_table) {
		acpi_os_unmap_memory(rsdp_address, rsdp_size);
		return (AE_NOT_FOUND);
	}

	gbl_rsdp_address =
	    rsdp_base + (ACPI_CAST8(mapped_table) - rsdp_address);

	memcpy(&gbl_rsdp, mapped_table, sizeof(struct acpi_table_rsdp));
	acpi_os_unmap_memory(rsdp_address, rsdp_size);

	return (AE_OK);
}
예제 #2
0
static acpi_status osl_list_customized_tables(char *directory)
{
	void *table_dir;
	u32 instance;
	char temp_name[ACPI_NAME_SIZE];
	char *filename;
	acpi_status status = AE_OK;

	/* Open the requested directory */

	table_dir = acpi_os_open_directory(directory, "*", REQUEST_FILE_ONLY);
	if (!table_dir) {
		return (osl_get_last_status(AE_NOT_FOUND));
	}

	/* Examine all entries in this directory */

	while ((filename = acpi_os_get_next_filename(table_dir))) {

		/* Extract table name and instance number */

		status =
		    osl_table_name_from_file(filename, temp_name, &instance);

		/* Ignore meaningless files */

		if (ACPI_FAILURE(status)) {
			continue;
		}

		/* Add new info node to global table list */

		status = osl_add_table_to_list(temp_name, instance);
		if (ACPI_FAILURE(status)) {
			break;
		}
	}

	acpi_os_close_directory(table_dir);
	return (status);
}
예제 #3
0
static acpi_status
osl_read_table_from_file(char *filename,
			 acpi_size file_offset,
			 char *signature, struct acpi_table_header **table)
{
	FILE *table_file;
	struct acpi_table_header header;
	struct acpi_table_header *local_table = NULL;
	u32 table_length;
	s32 count;
	acpi_status status = AE_OK;

	/* Open the file */

	table_file = fopen(filename, "rb");
	if (table_file == NULL) {
		fprintf(stderr, "Could not open table file: %s\n", filename);
		return (osl_get_last_status(AE_NOT_FOUND));
	}

	fseek(table_file, file_offset, SEEK_SET);

	/* Read the Table header to get the table length */

	count = fread(&header, 1, sizeof(struct acpi_table_header), table_file);
	if (count != sizeof(struct acpi_table_header)) {
		fprintf(stderr, "Could not read table header: %s\n", filename);
		status = AE_BAD_HEADER;
		goto exit;
	}

	/* If signature is specified, it must match the table */

	if (signature) {
		if (ACPI_VALIDATE_RSDP_SIG(signature)) {
			if (!ACPI_VALIDATE_RSDP_SIG(header.signature)) {
				fprintf(stderr,
					"Incorrect RSDP signature: found %8.8s\n",
					header.signature);
				status = AE_BAD_SIGNATURE;
				goto exit;
			}
		} else if (!ACPI_COMPARE_NAME(signature, header.signature)) {
			fprintf(stderr,
				"Incorrect signature: Expecting %4.4s, found %4.4s\n",
				signature, header.signature);
			status = AE_BAD_SIGNATURE;
			goto exit;
		}
	}

	table_length = ap_get_table_length(&header);
	if (table_length == 0) {
		status = AE_BAD_HEADER;
		goto exit;
	}

	/* Read the entire table into a local buffer */

	local_table = calloc(1, table_length);
	if (!local_table) {
		fprintf(stderr,
			"%4.4s: Could not allocate buffer for table of length %X\n",
			header.signature, table_length);
		status = AE_NO_MEMORY;
		goto exit;
	}

	fseek(table_file, file_offset, SEEK_SET);

	count = fread(local_table, 1, table_length, table_file);
	if (count != table_length) {
		fprintf(stderr, "%4.4s: Could not read table content\n",
			header.signature);
		status = AE_INVALID_TABLE_LENGTH;
		goto exit;
	}

	/* Validate checksum */

	(void)ap_is_valid_checksum(local_table);

exit:
	fclose(table_file);
	*table = local_table;
	return (status);
}
예제 #4
0
static acpi_status
osl_get_customized_table(char *pathname,
			 char *signature,
			 u32 instance,
			 struct acpi_table_header **table,
			 acpi_physical_address * address)
{
	void *table_dir;
	u32 current_instance = 0;
	char temp_name[ACPI_NAME_SIZE];
	char table_filename[PATH_MAX];
	char *filename;
	acpi_status status;

	/* Open the directory for customized tables */

	table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY);
	if (!table_dir) {
		return (osl_get_last_status(AE_NOT_FOUND));
	}

	/* Attempt to find the table in the directory */

	while ((filename = acpi_os_get_next_filename(table_dir))) {

		/* Ignore meaningless files */

		if (!ACPI_COMPARE_NAME(filename, signature)) {
			continue;
		}

		/* Extract table name and instance number */

		status =
		    osl_table_name_from_file(filename, temp_name,
					     &current_instance);

		/* Ignore meaningless files */

		if (ACPI_FAILURE(status) || current_instance != instance) {
			continue;
		}

		/* Create the table pathname */

		if (instance != 0) {
			sprintf(table_filename, "%s/%4.4s%d", pathname,
				temp_name, instance);
		} else {
			sprintf(table_filename, "%s/%4.4s", pathname,
				temp_name);
		}
		break;
	}

	acpi_os_close_directory(table_dir);

	if (!filename) {
		return (AE_LIMIT);
	}

	/* There is no physical address saved for customized tables, use zero */

	*address = 0;
	status = osl_read_table_from_file(table_filename, 0, NULL, table);

	return (status);
}
예제 #5
0
static acpi_status
osl_map_table(acpi_size address,
	      char *signature, struct acpi_table_header **table)
{
	struct acpi_table_header *mapped_table;
	u32 length;

	if (!address) {
		return (AE_BAD_ADDRESS);
	}

	/*
	 * Map the header so we can get the table length.
	 * Use sizeof (struct acpi_table_header) as:
	 * 1. it is bigger than 24 to include RSDP->Length
	 * 2. it is smaller than sizeof (struct acpi_table_rsdp)
	 */
	mapped_table =
	    acpi_os_map_memory(address, sizeof(struct acpi_table_header));
	if (!mapped_table) {
		fprintf(stderr, "Could not map table header at 0x%8.8X%8.8X\n",
			ACPI_FORMAT_UINT64(address));
		return (osl_get_last_status(AE_BAD_ADDRESS));
	}

	/* If specified, signature must match */

	if (signature) {
		if (ACPI_VALIDATE_RSDP_SIG(signature)) {
			if (!ACPI_VALIDATE_RSDP_SIG(mapped_table->signature)) {
				acpi_os_unmap_memory(mapped_table,
						     sizeof(struct
							    acpi_table_header));
				return (AE_BAD_SIGNATURE);
			}
		} else
		    if (!ACPI_COMPARE_NAME(signature, mapped_table->signature))
		{
			acpi_os_unmap_memory(mapped_table,
					     sizeof(struct acpi_table_header));
			return (AE_BAD_SIGNATURE);
		}
	}

	/* Map the entire table */

	length = ap_get_table_length(mapped_table);
	acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
	if (length == 0) {
		return (AE_BAD_HEADER);
	}

	mapped_table = acpi_os_map_memory(address, length);
	if (!mapped_table) {
		fprintf(stderr,
			"Could not map table at 0x%8.8X%8.8X length %8.8X\n",
			ACPI_FORMAT_UINT64(address), length);
		return (osl_get_last_status(AE_INVALID_TABLE_LENGTH));
	}

	(void)ap_is_valid_checksum(mapped_table);

	*table = mapped_table;
	return (AE_OK);
}