Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "actables.h"
0013 
0014 #define _COMPONENT          ACPI_TABLES
0015 ACPI_MODULE_NAME("tbxfroot")
0016 
0017 /*******************************************************************************
0018  *
0019  * FUNCTION:    acpi_tb_get_rsdp_length
0020  *
0021  * PARAMETERS:  rsdp                - Pointer to RSDP
0022  *
0023  * RETURN:      Table length
0024  *
0025  * DESCRIPTION: Get the length of the RSDP
0026  *
0027  ******************************************************************************/
0028 u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp)
0029 {
0030 
0031     if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
0032 
0033         /* BAD Signature */
0034 
0035         return (0);
0036     }
0037 
0038     /* "Length" field is available if table version >= 2 */
0039 
0040     if (rsdp->revision >= 2) {
0041         return (rsdp->length);
0042     } else {
0043         return (ACPI_RSDP_CHECKSUM_LENGTH);
0044     }
0045 }
0046 
0047 /*******************************************************************************
0048  *
0049  * FUNCTION:    acpi_tb_validate_rsdp
0050  *
0051  * PARAMETERS:  rsdp                - Pointer to unvalidated RSDP
0052  *
0053  * RETURN:      Status
0054  *
0055  * DESCRIPTION: Validate the RSDP (ptr)
0056  *
0057  ******************************************************************************/
0058 
0059 acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
0060 {
0061 
0062     /*
0063      * The signature and checksum must both be correct
0064      *
0065      * Note: Sometimes there exists more than one RSDP in memory; the valid
0066      * RSDP has a valid checksum, all others have an invalid checksum.
0067      */
0068     if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
0069 
0070         /* Nope, BAD Signature */
0071 
0072         return (AE_BAD_SIGNATURE);
0073     }
0074 
0075     /* Check the standard checksum */
0076 
0077     if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
0078         return (AE_BAD_CHECKSUM);
0079     }
0080 
0081     /* Check extended checksum if table version >= 2 */
0082 
0083     if ((rsdp->revision >= 2) &&
0084         (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
0085         return (AE_BAD_CHECKSUM);
0086     }
0087 
0088     return (AE_OK);
0089 }
0090 
0091 /*******************************************************************************
0092  *
0093  * FUNCTION:    acpi_find_root_pointer
0094  *
0095  * PARAMETERS:  table_address           - Where the table pointer is returned
0096  *
0097  * RETURN:      Status, RSDP physical address
0098  *
0099  * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
0100  *              pointer structure. If it is found, set *RSDP to point to it.
0101  *
0102  * NOTE1:       The RSDP must be either in the first 1K of the Extended
0103  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
0104  *              Only a 32-bit physical address is necessary.
0105  *
0106  * NOTE2:       This function is always available, regardless of the
0107  *              initialization state of the rest of ACPI.
0108  *
0109  ******************************************************************************/
0110 
0111 acpi_status ACPI_INIT_FUNCTION
0112 acpi_find_root_pointer(acpi_physical_address *table_address)
0113 {
0114     u8 *table_ptr;
0115     u8 *mem_rover;
0116     u32 physical_address;
0117 
0118     ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
0119 
0120     /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
0121 
0122     table_ptr = acpi_os_map_memory((acpi_physical_address)
0123                        ACPI_EBDA_PTR_LOCATION,
0124                        ACPI_EBDA_PTR_LENGTH);
0125     if (!table_ptr) {
0126         ACPI_ERROR((AE_INFO,
0127                 "Could not map memory at 0x%8.8X for length %u",
0128                 ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
0129 
0130         return_ACPI_STATUS(AE_NO_MEMORY);
0131     }
0132 
0133     ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
0134 
0135     /* Convert segment part to physical address */
0136 
0137     physical_address <<= 4;
0138     acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
0139 
0140     /* EBDA present? */
0141 
0142     if (physical_address > 0x400) {
0143         /*
0144          * 1b) Search EBDA paragraphs (EBDA is required to be a
0145          *     minimum of 1K length)
0146          */
0147         table_ptr = acpi_os_map_memory((acpi_physical_address)
0148                            physical_address,
0149                            ACPI_EBDA_WINDOW_SIZE);
0150         if (!table_ptr) {
0151             ACPI_ERROR((AE_INFO,
0152                     "Could not map memory at 0x%8.8X for length %u",
0153                     physical_address, ACPI_EBDA_WINDOW_SIZE));
0154 
0155             return_ACPI_STATUS(AE_NO_MEMORY);
0156         }
0157 
0158         mem_rover =
0159             acpi_tb_scan_memory_for_rsdp(table_ptr,
0160                          ACPI_EBDA_WINDOW_SIZE);
0161         acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
0162 
0163         if (mem_rover) {
0164 
0165             /* Return the physical address */
0166 
0167             physical_address +=
0168                 (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
0169 
0170             *table_address =
0171                 (acpi_physical_address)physical_address;
0172             return_ACPI_STATUS(AE_OK);
0173         }
0174     }
0175 
0176     /*
0177      * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
0178      */
0179     table_ptr = acpi_os_map_memory((acpi_physical_address)
0180                        ACPI_HI_RSDP_WINDOW_BASE,
0181                        ACPI_HI_RSDP_WINDOW_SIZE);
0182 
0183     if (!table_ptr) {
0184         ACPI_ERROR((AE_INFO,
0185                 "Could not map memory at 0x%8.8X for length %u",
0186                 ACPI_HI_RSDP_WINDOW_BASE,
0187                 ACPI_HI_RSDP_WINDOW_SIZE));
0188 
0189         return_ACPI_STATUS(AE_NO_MEMORY);
0190     }
0191 
0192     mem_rover =
0193         acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
0194     acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
0195 
0196     if (mem_rover) {
0197 
0198         /* Return the physical address */
0199 
0200         physical_address = (u32)
0201             (ACPI_HI_RSDP_WINDOW_BASE +
0202              ACPI_PTR_DIFF(mem_rover, table_ptr));
0203 
0204         *table_address = (acpi_physical_address)physical_address;
0205         return_ACPI_STATUS(AE_OK);
0206     }
0207 
0208     /* A valid RSDP was not found */
0209 
0210     ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found"));
0211     return_ACPI_STATUS(AE_NOT_FOUND);
0212 }
0213 
0214 ACPI_EXPORT_SYMBOL_INIT(acpi_find_root_pointer)
0215 
0216 /*******************************************************************************
0217  *
0218  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
0219  *
0220  * PARAMETERS:  start_address       - Starting pointer for search
0221  *              length              - Maximum length to search
0222  *
0223  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
0224  *
0225  * DESCRIPTION: Search a block of memory for the RSDP signature
0226  *
0227  ******************************************************************************/
0228 u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
0229 {
0230     acpi_status status;
0231     u8 *mem_rover;
0232     u8 *end_address;
0233 
0234     ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
0235 
0236     end_address = start_address + length;
0237 
0238     /* Search from given start address for the requested length */
0239 
0240     for (mem_rover = start_address; mem_rover < end_address;
0241          mem_rover += ACPI_RSDP_SCAN_STEP) {
0242 
0243         /* The RSDP signature and checksum must both be correct */
0244 
0245         status =
0246             acpi_tb_validate_rsdp(ACPI_CAST_PTR
0247                       (struct acpi_table_rsdp, mem_rover));
0248         if (ACPI_SUCCESS(status)) {
0249 
0250             /* Sig and checksum valid, we have found a real RSDP */
0251 
0252             ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0253                       "RSDP located at physical address %p\n",
0254                       mem_rover));
0255             return_PTR(mem_rover);
0256         }
0257 
0258         /* No sig match or bad checksum, keep searching */
0259     }
0260 
0261     /* Searched entire block, no RSDP was found */
0262 
0263     ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0264               "Searched entire block from %p, valid RSDP was not found\n",
0265               start_address));
0266     return_PTR(NULL);
0267 }