root/drivers/acpi/acpica/tbxfroot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_tb_validate_rsdp
  3. acpi_find_root_pointer
  4. ACPI_EXPORT_SYMBOL_INIT

   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 - 2019, 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_tb_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_tb_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 
 118         ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
 119 
 120         /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
 121 
 122         table_ptr = acpi_os_map_memory((acpi_physical_address)
 123                                        ACPI_EBDA_PTR_LOCATION,
 124                                        ACPI_EBDA_PTR_LENGTH);
 125         if (!table_ptr) {
 126                 ACPI_ERROR((AE_INFO,
 127                             "Could not map memory at 0x%8.8X for length %u",
 128                             ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
 129 
 130                 return_ACPI_STATUS(AE_NO_MEMORY);
 131         }
 132 
 133         ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
 134 
 135         /* Convert segment part to physical address */
 136 
 137         physical_address <<= 4;
 138         acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
 139 
 140         /* EBDA present? */
 141 
 142         if (physical_address > 0x400) {
 143                 /*
 144                  * 1b) Search EBDA paragraphs (EBDA is required to be a
 145                  *     minimum of 1K length)
 146                  */
 147                 table_ptr = acpi_os_map_memory((acpi_physical_address)
 148                                                physical_address,
 149                                                ACPI_EBDA_WINDOW_SIZE);
 150                 if (!table_ptr) {
 151                         ACPI_ERROR((AE_INFO,
 152                                     "Could not map memory at 0x%8.8X for length %u",
 153                                     physical_address, ACPI_EBDA_WINDOW_SIZE));
 154 
 155                         return_ACPI_STATUS(AE_NO_MEMORY);
 156                 }
 157 
 158                 mem_rover =
 159                     acpi_tb_scan_memory_for_rsdp(table_ptr,
 160                                                  ACPI_EBDA_WINDOW_SIZE);
 161                 acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
 162 
 163                 if (mem_rover) {
 164 
 165                         /* Return the physical address */
 166 
 167                         physical_address +=
 168                             (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 169 
 170                         *table_address =
 171                             (acpi_physical_address)physical_address;
 172                         return_ACPI_STATUS(AE_OK);
 173                 }
 174         }
 175 
 176         /*
 177          * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 178          */
 179         table_ptr = acpi_os_map_memory((acpi_physical_address)
 180                                        ACPI_HI_RSDP_WINDOW_BASE,
 181                                        ACPI_HI_RSDP_WINDOW_SIZE);
 182 
 183         if (!table_ptr) {
 184                 ACPI_ERROR((AE_INFO,
 185                             "Could not map memory at 0x%8.8X for length %u",
 186                             ACPI_HI_RSDP_WINDOW_BASE,
 187                             ACPI_HI_RSDP_WINDOW_SIZE));
 188 
 189                 return_ACPI_STATUS(AE_NO_MEMORY);
 190         }
 191 
 192         mem_rover =
 193             acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 194         acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 195 
 196         if (mem_rover) {
 197 
 198                 /* Return the physical address */
 199 
 200                 physical_address = (u32)
 201                     (ACPI_HI_RSDP_WINDOW_BASE +
 202                      ACPI_PTR_DIFF(mem_rover, table_ptr));
 203 
 204                 *table_address = (acpi_physical_address)physical_address;
 205                 return_ACPI_STATUS(AE_OK);
 206         }
 207 
 208         /* A valid RSDP was not found */
 209 
 210         ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found"));
 211         return_ACPI_STATUS(AE_NOT_FOUND);
 212 }
 213 
 214 ACPI_EXPORT_SYMBOL_INIT(acpi_find_root_pointer)
 215 
 216 /*******************************************************************************
 217  *
 218  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
 219  *
 220  * PARAMETERS:  start_address       - Starting pointer for search
 221  *              length              - Maximum length to search
 222  *
 223  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
 224  *
 225  * DESCRIPTION: Search a block of memory for the RSDP signature
 226  *
 227  ******************************************************************************/
 228 u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
 229 {
 230         acpi_status status;
 231         u8 *mem_rover;
 232         u8 *end_address;
 233 
 234         ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
 235 
 236         end_address = start_address + length;
 237 
 238         /* Search from given start address for the requested length */
 239 
 240         for (mem_rover = start_address; mem_rover < end_address;
 241              mem_rover += ACPI_RSDP_SCAN_STEP) {
 242 
 243                 /* The RSDP signature and checksum must both be correct */
 244 
 245                 status =
 246                     acpi_tb_validate_rsdp(ACPI_CAST_PTR
 247                                           (struct acpi_table_rsdp, mem_rover));
 248                 if (ACPI_SUCCESS(status)) {
 249 
 250                         /* Sig and checksum valid, we have found a real RSDP */
 251 
 252                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 253                                           "RSDP located at physical address %p\n",
 254                                           mem_rover));
 255                         return_PTR(mem_rover);
 256                 }
 257 
 258                 /* No sig match or bad checksum, keep searching */
 259         }
 260 
 261         /* Searched entire block, no RSDP was found */
 262 
 263         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 264                           "Searched entire block from %p, valid RSDP was not found\n",
 265                           start_address));
 266         return_PTR(NULL);
 267 }

/* [<][>][^][v][top][bottom][index][help] */