linux/drivers/acpi/acpica/tbxfroot.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: tbxfroot - Find the root ACPI table (RSDT)
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2016, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "actables.h"
  47
  48#define _COMPONENT          ACPI_TABLES
  49ACPI_MODULE_NAME("tbxfroot")
  50
  51/*******************************************************************************
  52 *
  53 * FUNCTION:    acpi_tb_get_rsdp_length
  54 *
  55 * PARAMETERS:  rsdp                - Pointer to RSDP
  56 *
  57 * RETURN:      Table length
  58 *
  59 * DESCRIPTION: Get the length of the RSDP
  60 *
  61 ******************************************************************************/
  62u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp)
  63{
  64
  65        if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
  66
  67                /* BAD Signature */
  68
  69                return (0);
  70        }
  71
  72        /* "Length" field is available if table version >= 2 */
  73
  74        if (rsdp->revision >= 2) {
  75                return (rsdp->length);
  76        } else {
  77                return (ACPI_RSDP_CHECKSUM_LENGTH);
  78        }
  79}
  80
  81/*******************************************************************************
  82 *
  83 * FUNCTION:    acpi_tb_validate_rsdp
  84 *
  85 * PARAMETERS:  rsdp                - Pointer to unvalidated RSDP
  86 *
  87 * RETURN:      Status
  88 *
  89 * DESCRIPTION: Validate the RSDP (ptr)
  90 *
  91 ******************************************************************************/
  92
  93acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp * rsdp)
  94{
  95
  96        /*
  97         * The signature and checksum must both be correct
  98         *
  99         * Note: Sometimes there exists more than one RSDP in memory; the valid
 100         * RSDP has a valid checksum, all others have an invalid checksum.
 101         */
 102        if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
 103
 104                /* Nope, BAD Signature */
 105
 106                return (AE_BAD_SIGNATURE);
 107        }
 108
 109        /* Check the standard checksum */
 110
 111        if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
 112                return (AE_BAD_CHECKSUM);
 113        }
 114
 115        /* Check extended checksum if table version >= 2 */
 116
 117        if ((rsdp->revision >= 2) &&
 118            (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
 119                return (AE_BAD_CHECKSUM);
 120        }
 121
 122        return (AE_OK);
 123}
 124
 125/*******************************************************************************
 126 *
 127 * FUNCTION:    acpi_find_root_pointer
 128 *
 129 * PARAMETERS:  table_address           - Where the table pointer is returned
 130 *
 131 * RETURN:      Status, RSDP physical address
 132 *
 133 * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
 134 *              pointer structure. If it is found, set *RSDP to point to it.
 135 *
 136 * NOTE1:       The RSDP must be either in the first 1K of the Extended
 137 *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
 138 *              Only a 32-bit physical address is necessary.
 139 *
 140 * NOTE2:       This function is always available, regardless of the
 141 *              initialization state of the rest of ACPI.
 142 *
 143 ******************************************************************************/
 144
 145acpi_status __init acpi_find_root_pointer(acpi_physical_address * table_address)
 146{
 147        u8 *table_ptr;
 148        u8 *mem_rover;
 149        u32 physical_address;
 150
 151        ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
 152
 153        /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
 154
 155        table_ptr = acpi_os_map_memory((acpi_physical_address)
 156                                       ACPI_EBDA_PTR_LOCATION,
 157                                       ACPI_EBDA_PTR_LENGTH);
 158        if (!table_ptr) {
 159                ACPI_ERROR((AE_INFO,
 160                            "Could not map memory at 0x%8.8X for length %u",
 161                            ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
 162
 163                return_ACPI_STATUS(AE_NO_MEMORY);
 164        }
 165
 166        ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
 167
 168        /* Convert segment part to physical address */
 169
 170        physical_address <<= 4;
 171        acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
 172
 173        /* EBDA present? */
 174
 175        if (physical_address > 0x400) {
 176                /*
 177                 * 1b) Search EBDA paragraphs (EBDA is required to be a
 178                 *     minimum of 1K length)
 179                 */
 180                table_ptr = acpi_os_map_memory((acpi_physical_address)
 181                                               physical_address,
 182                                               ACPI_EBDA_WINDOW_SIZE);
 183                if (!table_ptr) {
 184                        ACPI_ERROR((AE_INFO,
 185                                    "Could not map memory at 0x%8.8X for length %u",
 186                                    physical_address, ACPI_EBDA_WINDOW_SIZE));
 187
 188                        return_ACPI_STATUS(AE_NO_MEMORY);
 189                }
 190
 191                mem_rover =
 192                    acpi_tb_scan_memory_for_rsdp(table_ptr,
 193                                                 ACPI_EBDA_WINDOW_SIZE);
 194                acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
 195
 196                if (mem_rover) {
 197
 198                        /* Return the physical address */
 199
 200                        physical_address +=
 201                            (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 202
 203                        *table_address =
 204                            (acpi_physical_address) physical_address;
 205                        return_ACPI_STATUS(AE_OK);
 206                }
 207        }
 208
 209        /*
 210         * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 211         */
 212        table_ptr = acpi_os_map_memory((acpi_physical_address)
 213                                       ACPI_HI_RSDP_WINDOW_BASE,
 214                                       ACPI_HI_RSDP_WINDOW_SIZE);
 215
 216        if (!table_ptr) {
 217                ACPI_ERROR((AE_INFO,
 218                            "Could not map memory at 0x%8.8X for length %u",
 219                            ACPI_HI_RSDP_WINDOW_BASE,
 220                            ACPI_HI_RSDP_WINDOW_SIZE));
 221
 222                return_ACPI_STATUS(AE_NO_MEMORY);
 223        }
 224
 225        mem_rover =
 226            acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 227        acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 228
 229        if (mem_rover) {
 230
 231                /* Return the physical address */
 232
 233                physical_address = (u32)
 234                    (ACPI_HI_RSDP_WINDOW_BASE +
 235                     ACPI_PTR_DIFF(mem_rover, table_ptr));
 236
 237                *table_address = (acpi_physical_address) physical_address;
 238                return_ACPI_STATUS(AE_OK);
 239        }
 240
 241        /* A valid RSDP was not found */
 242
 243        ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found"));
 244        return_ACPI_STATUS(AE_NOT_FOUND);
 245}
 246
 247/*******************************************************************************
 248 *
 249 * FUNCTION:    acpi_tb_scan_memory_for_rsdp
 250 *
 251 * PARAMETERS:  start_address       - Starting pointer for search
 252 *              length              - Maximum length to search
 253 *
 254 * RETURN:      Pointer to the RSDP if found, otherwise NULL.
 255 *
 256 * DESCRIPTION: Search a block of memory for the RSDP signature
 257 *
 258 ******************************************************************************/
 259u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
 260{
 261        acpi_status status;
 262        u8 *mem_rover;
 263        u8 *end_address;
 264
 265        ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
 266
 267        end_address = start_address + length;
 268
 269        /* Search from given start address for the requested length */
 270
 271        for (mem_rover = start_address; mem_rover < end_address;
 272             mem_rover += ACPI_RSDP_SCAN_STEP) {
 273
 274                /* The RSDP signature and checksum must both be correct */
 275
 276                status =
 277                    acpi_tb_validate_rsdp(ACPI_CAST_PTR
 278                                          (struct acpi_table_rsdp, mem_rover));
 279                if (ACPI_SUCCESS(status)) {
 280
 281                        /* Sig and checksum valid, we have found a real RSDP */
 282
 283                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 284                                          "RSDP located at physical address %p\n",
 285                                          mem_rover));
 286                        return_PTR(mem_rover);
 287                }
 288
 289                /* No sig match or bad checksum, keep searching */
 290        }
 291
 292        /* Searched entire block, no RSDP was found */
 293
 294        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 295                          "Searched entire block from %p, valid RSDP was not found\n",
 296                          start_address));
 297        return_PTR(NULL);
 298}
 299