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); }
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); }
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); }
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, ¤t_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); }
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); }