1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: tbxfroot - Find the root ACPI table (RSDT) 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "actables.h" 13 14 #define _COMPONENT ACPI_TABLES 15 ACPI_MODULE_NAME("tbxfroot") 16 17 /******************************************************************************* 18 * 19 * FUNCTION: acpi_tb_get_rsdp_length 20 * 21 * PARAMETERS: rsdp - Pointer to RSDP 22 * 23 * RETURN: Table length 24 * 25 * DESCRIPTION: Get the length of the RSDP 26 * 27 ******************************************************************************/ 28 u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp) 29 { 30 31 if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { 32 33 /* BAD Signature */ 34 35 return (0); 36 } 37 38 /* "Length" field is available if table version >= 2 */ 39 40 if (rsdp->revision >= 2) { 41 return (rsdp->length); 42 } else { 43 return (ACPI_RSDP_CHECKSUM_LENGTH); 44 } 45 } 46 47 /******************************************************************************* 48 * 49 * FUNCTION: acpi_tb_validate_rsdp 50 * 51 * PARAMETERS: rsdp - Pointer to unvalidated RSDP 52 * 53 * RETURN: Status 54 * 55 * DESCRIPTION: Validate the RSDP (ptr) 56 * 57 ******************************************************************************/ 58 59 acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) 60 { 61 62 /* 63 * The signature and checksum must both be correct 64 * 65 * Note: Sometimes there exists more than one RSDP in memory; the valid 66 * RSDP has a valid checksum, all others have an invalid checksum. 67 */ 68 if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { 69 70 /* Nope, BAD Signature */ 71 72 return (AE_BAD_SIGNATURE); 73 } 74 75 /* Check the standard checksum */ 76 77 if (acpi_ut_checksum((u8 *)rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { 78 return (AE_BAD_CHECKSUM); 79 } 80 81 /* Check extended checksum if table version >= 2 */ 82 83 if ((rsdp->revision >= 2) && 84 (acpi_ut_checksum((u8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { 85 return (AE_BAD_CHECKSUM); 86 } 87 88 return (AE_OK); 89 } 90 91 /******************************************************************************* 92 * 93 * FUNCTION: acpi_find_root_pointer 94 * 95 * PARAMETERS: table_address - Where the table pointer is returned 96 * 97 * RETURN: Status, RSDP physical address 98 * 99 * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor 100 * pointer structure. If it is found, set *RSDP to point to it. 101 * 102 * NOTE1: The RSDP must be either in the first 1K of the Extended 103 * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) 104 * Only a 32-bit physical address is necessary. 105 * 106 * NOTE2: This function is always available, regardless of the 107 * initialization state of the rest of ACPI. 108 * 109 ******************************************************************************/ 110 111 acpi_status ACPI_INIT_FUNCTION 112 acpi_find_root_pointer(acpi_physical_address *table_address) 113 { 114 u8 *table_ptr; 115 u8 *mem_rover; 116 u32 physical_address; 117 u32 ebda_window_size; 118 119 ACPI_FUNCTION_TRACE(acpi_find_root_pointer); 120 121 /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ 122 123 table_ptr = acpi_os_map_memory((acpi_physical_address) 124 ACPI_EBDA_PTR_LOCATION, 125 ACPI_EBDA_PTR_LENGTH); 126 if (!table_ptr) { 127 ACPI_ERROR((AE_INFO, 128 "Could not map memory at 0x%8.8X for length %u", 129 ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); 130 131 return_ACPI_STATUS(AE_NO_MEMORY); 132 } 133 134 ACPI_MOVE_16_TO_32(&physical_address, table_ptr); 135 136 /* Convert segment part to physical address */ 137 138 physical_address <<= 4; 139 acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); 140 141 /* EBDA present? */ 142 143 /* 144 * Check that the EBDA pointer from memory is sane and does not point 145 * above valid low memory 146 */ 147 if (physical_address > 0x400 && physical_address < 0xA0000) { 148 /* 149 * Calculate the scan window size 150 * The EBDA is not guaranteed to be larger than a ki_b and in case 151 * that it is smaller, the scanning function would leave the low 152 * memory and continue to the VGA range. 153 */ 154 ebda_window_size = ACPI_MIN(ACPI_EBDA_WINDOW_SIZE, 155 0xA0000 - physical_address); 156 157 /* 158 * 1b) Search EBDA paragraphs 159 */ 160 table_ptr = acpi_os_map_memory((acpi_physical_address) 161 physical_address, 162 ebda_window_size); 163 if (!table_ptr) { 164 ACPI_ERROR((AE_INFO, 165 "Could not map memory at 0x%8.8X for length %u", 166 physical_address, ebda_window_size)); 167 168 return_ACPI_STATUS(AE_NO_MEMORY); 169 } 170 171 mem_rover = 172 acpi_tb_scan_memory_for_rsdp(table_ptr, ebda_window_size); 173 acpi_os_unmap_memory(table_ptr, ebda_window_size); 174 175 if (mem_rover) { 176 177 /* Return the physical address */ 178 179 physical_address += 180 (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); 181 182 *table_address = 183 (acpi_physical_address)physical_address; 184 return_ACPI_STATUS(AE_OK); 185 } 186 } 187 188 /* 189 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh 190 */ 191 table_ptr = acpi_os_map_memory((acpi_physical_address) 192 ACPI_HI_RSDP_WINDOW_BASE, 193 ACPI_HI_RSDP_WINDOW_SIZE); 194 195 if (!table_ptr) { 196 ACPI_ERROR((AE_INFO, 197 "Could not map memory at 0x%8.8X for length %u", 198 ACPI_HI_RSDP_WINDOW_BASE, 199 ACPI_HI_RSDP_WINDOW_SIZE)); 200 201 return_ACPI_STATUS(AE_NO_MEMORY); 202 } 203 204 mem_rover = 205 acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); 206 acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); 207 208 if (mem_rover) { 209 210 /* Return the physical address */ 211 212 physical_address = (u32) 213 (ACPI_HI_RSDP_WINDOW_BASE + 214 ACPI_PTR_DIFF(mem_rover, table_ptr)); 215 216 *table_address = (acpi_physical_address)physical_address; 217 return_ACPI_STATUS(AE_OK); 218 } 219 220 /* A valid RSDP was not found */ 221 222 ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found")); 223 return_ACPI_STATUS(AE_NOT_FOUND); 224 } 225 226 ACPI_EXPORT_SYMBOL_INIT(acpi_find_root_pointer) 227 228 /******************************************************************************* 229 * 230 * FUNCTION: acpi_tb_scan_memory_for_rsdp 231 * 232 * PARAMETERS: start_address - Starting pointer for search 233 * length - Maximum length to search 234 * 235 * RETURN: Pointer to the RSDP if found, otherwise NULL. 236 * 237 * DESCRIPTION: Search a block of memory for the RSDP signature 238 * 239 ******************************************************************************/ 240 u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length) 241 { 242 acpi_status status; 243 u8 *mem_rover; 244 u8 *end_address; 245 246 ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp); 247 248 end_address = start_address + length; 249 250 /* Search from given start address for the requested length */ 251 252 for (mem_rover = start_address; mem_rover < end_address; 253 mem_rover += ACPI_RSDP_SCAN_STEP) { 254 255 /* The RSDP signature and checksum must both be correct */ 256 257 status = 258 acpi_tb_validate_rsdp(ACPI_CAST_PTR 259 (struct acpi_table_rsdp, mem_rover)); 260 if (ACPI_SUCCESS(status)) { 261 262 /* Sig and checksum valid, we have found a real RSDP */ 263 264 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 265 "RSDP located at physical address %p\n", 266 mem_rover)); 267 return_PTR(mem_rover); 268 } 269 270 /* No sig match or bad checksum, keep searching */ 271 } 272 273 /* Searched entire block, no RSDP was found */ 274 275 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 276 "Searched entire block from %p, valid RSDP was not found\n", 277 start_address)); 278 return_PTR(NULL); 279 } 280