linux-old/drivers/acpi/tables/tbxfroot.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: tbxfroot - Find the root ACPI table (RSDT)
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2004, R. Byron Moore
   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
  45#include <acpi/acpi.h>
  46#include <acpi/actables.h>
  47
  48
  49#define _COMPONENT          ACPI_TABLES
  50         ACPI_MODULE_NAME    ("tbxfroot")
  51
  52
  53/*******************************************************************************
  54 *
  55 * FUNCTION:    acpi_tb_find_table
  56 *
  57 * PARAMETERS:  Signature           - String with ACPI table signature
  58 *              oem_id              - String with the table OEM ID
  59 *              oem_table_id        - String with the OEM Table ID.
  60 *
  61 * RETURN:      Status
  62 *
  63 * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
  64 *              Signature, OEM ID and OEM Table ID.
  65 *
  66 ******************************************************************************/
  67
  68acpi_status
  69acpi_tb_find_table (
  70        char                            *signature,
  71        char                            *oem_id,
  72        char                            *oem_table_id,
  73        struct acpi_table_header        **table_ptr)
  74{
  75        acpi_status                     status;
  76        struct acpi_table_header        *table;
  77
  78
  79        ACPI_FUNCTION_TRACE ("tb_find_table");
  80
  81
  82        /* Validate string lengths */
  83
  84        if ((ACPI_STRLEN (signature)  > ACPI_NAME_SIZE) ||
  85                (ACPI_STRLEN (oem_id)     > sizeof (table->oem_id)) ||
  86                (ACPI_STRLEN (oem_table_id) > sizeof (table->oem_table_id))) {
  87                return_ACPI_STATUS (AE_AML_STRING_LIMIT);
  88        }
  89
  90        /* Find the table */
  91
  92        status = acpi_get_firmware_table (signature, 1,
  93                           ACPI_LOGICAL_ADDRESSING, &table);
  94        if (ACPI_FAILURE (status)) {
  95                return_ACPI_STATUS (status);
  96        }
  97
  98        /* Check oem_id and oem_table_id */
  99
 100        if ((oem_id[0]     && ACPI_STRCMP (oem_id, table->oem_id)) ||
 101                (oem_table_id[0] && ACPI_STRCMP (oem_table_id, table->oem_table_id))) {
 102                return_ACPI_STATUS (AE_AML_NAME_NOT_FOUND);
 103        }
 104
 105        *table_ptr = table;
 106        return_ACPI_STATUS (AE_OK);
 107}
 108
 109
 110/*******************************************************************************
 111 *
 112 * FUNCTION:    acpi_get_firmware_table
 113 *
 114 * PARAMETERS:  Signature       - Any ACPI table signature
 115 *              Instance        - the non zero instance of the table, allows
 116 *                                support for multiple tables of the same type
 117 *              Flags           - Physical/Virtual support
 118 *              ret_buffer      - pointer to a structure containing a buffer to
 119 *                                receive the table
 120 *
 121 * RETURN:      Status
 122 *
 123 * DESCRIPTION: This function is called to get an ACPI table.  The caller
 124 *              supplies an out_buffer large enough to contain the entire ACPI
 125 *              table.  Upon completion
 126 *              the out_buffer->Length field will indicate the number of bytes
 127 *              copied into the out_buffer->buf_ptr buffer. This table will be
 128 *              a complete table including the header.
 129 *
 130 ******************************************************************************/
 131
 132acpi_status
 133acpi_get_firmware_table (
 134        acpi_string                     signature,
 135        u32                             instance,
 136        u32                             flags,
 137        struct acpi_table_header        **table_pointer)
 138{
 139        struct acpi_pointer             rsdp_address;
 140        struct acpi_pointer             address;
 141        acpi_status                     status;
 142        struct acpi_table_header        header;
 143        struct acpi_table_desc          table_info;
 144        struct acpi_table_desc          rsdt_info;
 145        u32                             table_count;
 146        u32                             i;
 147        u32                             j;
 148
 149
 150        ACPI_FUNCTION_TRACE ("acpi_get_firmware_table");
 151
 152
 153        /*
 154         * Ensure that at least the table manager is initialized.  We don't
 155         * require that the entire ACPI subsystem is up for this interface
 156         */
 157
 158        /*
 159         *  If we have a buffer, we must have a length too
 160         */
 161        if ((instance == 0)                 ||
 162                (!signature)                    ||
 163                (!table_pointer)) {
 164                return_ACPI_STATUS (AE_BAD_PARAMETER);
 165        }
 166
 167        rsdt_info.pointer = NULL;
 168
 169        if (!acpi_gbl_RSDP) {
 170                /* Get the RSDP */
 171
 172                status = acpi_os_get_root_pointer (flags, &rsdp_address);
 173                if (ACPI_FAILURE (status)) {
 174                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not found\n"));
 175                        return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 176                }
 177
 178                /* Map and validate the RSDP */
 179
 180                if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
 181                        status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor),
 182                                          (void *) &acpi_gbl_RSDP);
 183                        if (ACPI_FAILURE (status)) {
 184                                return_ACPI_STATUS (status);
 185                        }
 186                }
 187                else {
 188                        acpi_gbl_RSDP = rsdp_address.pointer.logical;
 189                }
 190
 191                /*
 192                 *  The signature and checksum must both be correct
 193                 */
 194                if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
 195                        /* Nope, BAD Signature */
 196
 197                        return_ACPI_STATUS (AE_BAD_SIGNATURE);
 198                }
 199
 200                if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
 201                        /* Nope, BAD Checksum */
 202
 203                        return_ACPI_STATUS (AE_BAD_CHECKSUM);
 204                }
 205        }
 206
 207        /* Get the RSDT and validate it */
 208
 209        acpi_tb_get_rsdt_address (&address);
 210
 211        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 212                "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
 213                acpi_gbl_RSDP,
 214                ACPI_FORMAT_UINT64 (address.pointer.value)));
 215
 216        /* Insert processor_mode flags */
 217
 218        address.pointer_type |= flags;
 219
 220        status = acpi_tb_get_table (&address, &rsdt_info);
 221        if (ACPI_FAILURE (status)) {
 222                return_ACPI_STATUS (status);
 223        }
 224
 225        status = acpi_tb_validate_rsdt (rsdt_info.pointer);
 226        if (ACPI_FAILURE (status)) {
 227                goto cleanup;
 228        }
 229
 230        /* Get the number of table pointers within the RSDT */
 231
 232        table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer);
 233
 234        address.pointer_type = acpi_gbl_table_flags | flags;
 235
 236        /*
 237         * Search the RSDT/XSDT for the correct instance of the
 238         * requested table
 239         */
 240        for (i = 0, j = 0; i < table_count; i++) {
 241                /* Get the next table pointer, handle RSDT vs. XSDT */
 242
 243                if (acpi_gbl_RSDP->revision < 2) {
 244                        address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
 245                }
 246                else {
 247                        address.pointer.value =
 248                                (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
 249                }
 250
 251                /* Get the table header */
 252
 253                status = acpi_tb_get_table_header (&address, &header);
 254                if (ACPI_FAILURE (status)) {
 255                        goto cleanup;
 256                }
 257
 258                /* Compare table signatures and table instance */
 259
 260                if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
 261                        /* An instance of the table was found */
 262
 263                        j++;
 264                        if (j >= instance) {
 265                                /* Found the correct instance, get the entire table */
 266
 267                                status = acpi_tb_get_table_body (&address, &header, &table_info);
 268                                if (ACPI_FAILURE (status)) {
 269                                        goto cleanup;
 270                                }
 271
 272                                *table_pointer = table_info.pointer;
 273                                goto cleanup;
 274                        }
 275                }
 276        }
 277
 278        /* Did not find the table */
 279
 280        status = AE_NOT_EXIST;
 281
 282
 283cleanup:
 284        acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length);
 285        return_ACPI_STATUS (status);
 286}
 287
 288
 289/* TBD: Move to a new file */
 290
 291#if ACPI_MACHINE_WIDTH != 16
 292
 293/*******************************************************************************
 294 *
 295 * FUNCTION:    acpi_find_root_pointer
 296 *
 297 * PARAMETERS:  **rsdp_address          - Where to place the RSDP address
 298 *              Flags                   - Logical/Physical addressing
 299 *
 300 * RETURN:      Status, Physical address of the RSDP
 301 *
 302 * DESCRIPTION: Find the RSDP
 303 *
 304 ******************************************************************************/
 305
 306acpi_status
 307acpi_find_root_pointer (
 308        u32                             flags,
 309        struct acpi_pointer             *rsdp_address)
 310{
 311        struct acpi_table_desc          table_info;
 312        acpi_status                     status;
 313
 314
 315        ACPI_FUNCTION_TRACE ("acpi_find_root_pointer");
 316
 317
 318        /* Get the RSDP */
 319
 320        status = acpi_tb_find_rsdp (&table_info, flags);
 321        if (ACPI_FAILURE (status)) {
 322                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "RSDP structure not found, %s Flags=%X\n",
 323                        acpi_format_exception (status), flags));
 324                return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 325        }
 326
 327        rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
 328        rsdp_address->pointer.physical = table_info.physical_address;
 329        return_ACPI_STATUS (AE_OK);
 330}
 331
 332
 333/*******************************************************************************
 334 *
 335 * FUNCTION:    acpi_tb_scan_memory_for_rsdp
 336 *
 337 * PARAMETERS:  start_address       - Starting pointer for search
 338 *              Length              - Maximum length to search
 339 *
 340 * RETURN:      Pointer to the RSDP if found, otherwise NULL.
 341 *
 342 * DESCRIPTION: Search a block of memory for the RSDP signature
 343 *
 344 ******************************************************************************/
 345
 346u8 *
 347acpi_tb_scan_memory_for_rsdp (
 348        u8                              *start_address,
 349        u32                             length)
 350{
 351        u32                             offset;
 352        u8                              *mem_rover;
 353
 354
 355        ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp");
 356
 357
 358        /* Search from given start addr for the requested length  */
 359
 360        for (offset = 0, mem_rover = start_address;
 361                 offset < length;
 362                 offset += ACPI_RSDP_SCAN_STEP, mem_rover += ACPI_RSDP_SCAN_STEP) {
 363
 364                /* The signature and checksum must both be correct */
 365
 366                if (ACPI_STRNCMP ((char *) mem_rover,
 367                                RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
 368                        acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH) == 0) {
 369                        /* If so, we have found the RSDP */
 370
 371                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 372                                "RSDP located at physical address %p\n",mem_rover));
 373                        return_PTR (mem_rover);
 374                }
 375        }
 376
 377        /* Searched entire block, no RSDP was found */
 378
 379        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,"Searched entire block, no RSDP was found.\n"));
 380        return_PTR (NULL);
 381}
 382
 383
 384/*******************************************************************************
 385 *
 386 * FUNCTION:    acpi_tb_find_rsdp
 387 *
 388 * PARAMETERS:  *table_info             - Where the table info is returned
 389 *              Flags                   - Current memory mode (logical vs.
 390 *                                        physical addressing)
 391 *
 392 * RETURN:      Status
 393 *
 394 * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
 395 *              pointer structure.  If it is found, set *RSDP to point to it.
 396 *
 397 *              NOTE: The RSDp must be either in the first 1_k of the Extended
 398 *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
 399 *              5.2.2; assertion #421).
 400 *
 401 ******************************************************************************/
 402
 403acpi_status
 404acpi_tb_find_rsdp (
 405        struct acpi_table_desc          *table_info,
 406        u32                             flags)
 407{
 408        u8                              *table_ptr;
 409        u8                              *mem_rover;
 410        u64                             phys_addr;
 411        acpi_status                     status = AE_OK;
 412
 413
 414        ACPI_FUNCTION_TRACE ("tb_find_rsdp");
 415
 416
 417        /*
 418         * Scan supports either 1) Logical addressing or 2) Physical addressing
 419         */
 420        if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
 421                /*
 422                 * 1) Search EBDA (low memory) paragraphs
 423                 */
 424                status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE,
 425                                  (void *) &table_ptr);
 426                if (ACPI_FAILURE (status)) {
 427                        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
 428                                ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE));
 429                        return_ACPI_STATUS (status);
 430                }
 431
 432                mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
 433                acpi_os_unmap_memory (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
 434
 435                if (mem_rover) {
 436                        /* Found it, return the physical address */
 437
 438                        phys_addr = ACPI_LO_RSDP_WINDOW_BASE;
 439                        phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr);
 440
 441                        table_info->physical_address = phys_addr;
 442                        return_ACPI_STATUS (AE_OK);
 443                }
 444
 445                /*
 446                 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
 447                 */
 448                status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE,
 449                                  (void *) &table_ptr);
 450                if (ACPI_FAILURE (status)) {
 451                        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
 452                                ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
 453                        return_ACPI_STATUS (status);
 454                }
 455
 456                mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 457                acpi_os_unmap_memory (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 458
 459                if (mem_rover) {
 460                        /* Found it, return the physical address */
 461
 462                        phys_addr = ACPI_HI_RSDP_WINDOW_BASE;
 463                        phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr);
 464
 465                        table_info->physical_address = phys_addr;
 466                        return_ACPI_STATUS (AE_OK);
 467                }
 468        }
 469
 470        /*
 471         * Physical addressing
 472         */
 473        else {
 474                /*
 475                 * 1) Search EBDA (low memory) paragraphs
 476                 */
 477                mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE),
 478                                  ACPI_LO_RSDP_WINDOW_SIZE);
 479                if (mem_rover) {
 480                        /* Found it, return the physical address */
 481
 482                        table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
 483                        return_ACPI_STATUS (AE_OK);
 484                }
 485
 486                /*
 487                 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
 488                 */
 489                mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
 490                                  ACPI_HI_RSDP_WINDOW_SIZE);
 491                if (mem_rover) {
 492                        /* Found it, return the physical address */
 493
 494                        table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
 495                        return_ACPI_STATUS (AE_OK);
 496                }
 497        }
 498
 499        /* RSDP signature was not found */
 500
 501        return_ACPI_STATUS (AE_NOT_FOUND);
 502}
 503
 504#endif
 505
 506
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.