tbxfroot.c revision 253690
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: tbxfroot - Find the root ACPI table (RSDT)
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
4467754Smsmith#define __TBXFROOT_C__
4567754Smsmith
46193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
47193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
48193341Sjkim#include <contrib/dev/acpica/include/actables.h>
4967754Smsmith
5067754Smsmith
5177424Smsmith#define _COMPONENT          ACPI_TABLES
5291116Smsmith        ACPI_MODULE_NAME    ("tbxfroot")
5367754Smsmith
5467754Smsmith
5567754Smsmith/*******************************************************************************
5667754Smsmith *
57151937Sjkim * FUNCTION:    AcpiTbValidateRsdp
58151937Sjkim *
59167802Sjkim * PARAMETERS:  Rsdp                - Pointer to unvalidated RSDP
60151937Sjkim *
61151937Sjkim * RETURN:      Status
62151937Sjkim *
63151937Sjkim * DESCRIPTION: Validate the RSDP (ptr)
64151937Sjkim *
65151937Sjkim ******************************************************************************/
66151937Sjkim
67253690SjkimACPI_STATUS
68151937SjkimAcpiTbValidateRsdp (
69167802Sjkim    ACPI_TABLE_RSDP         *Rsdp)
70151937Sjkim{
71151937Sjkim
72151937Sjkim    /*
73167802Sjkim     * The signature and checksum must both be correct
74167802Sjkim     *
75167802Sjkim     * Note: Sometimes there exists more than one RSDP in memory; the valid
76167802Sjkim     * RSDP has a valid checksum, all others have an invalid checksum.
77151937Sjkim     */
78253690Sjkim    if (ACPI_STRNCMP ((char *) Rsdp->Signature, ACPI_SIG_RSDP,
79193267Sjkim            sizeof (ACPI_SIG_RSDP)-1) != 0)
80151937Sjkim    {
81151937Sjkim        /* Nope, BAD Signature */
82151937Sjkim
83151937Sjkim        return (AE_BAD_SIGNATURE);
84151937Sjkim    }
85151937Sjkim
86151937Sjkim    /* Check the standard checksum */
87151937Sjkim
88167802Sjkim    if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
89151937Sjkim    {
90151937Sjkim        return (AE_BAD_CHECKSUM);
91151937Sjkim    }
92151937Sjkim
93151937Sjkim    /* Check extended checksum if table version >= 2 */
94151937Sjkim
95151937Sjkim    if ((Rsdp->Revision >= 2) &&
96167802Sjkim        (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0))
97151937Sjkim    {
98151937Sjkim        return (AE_BAD_CHECKSUM);
99151937Sjkim    }
100151937Sjkim
101151937Sjkim    return (AE_OK);
102151937Sjkim}
103151937Sjkim
104151937Sjkim
105151937Sjkim/*******************************************************************************
106151937Sjkim *
107193267Sjkim * FUNCTION:    AcpiFindRootPointer
10867754Smsmith *
109167802Sjkim * PARAMETERS:  TableAddress            - Where the table pointer is returned
11067754Smsmith *
111167802Sjkim * RETURN:      Status, RSDP physical address
11267754Smsmith *
113167802Sjkim * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
114241973Sjkim *              pointer structure. If it is found, set *RSDP to point to it.
11567754Smsmith *
116167802Sjkim * NOTE1:       The RSDP must be either in the first 1K of the Extended
117167802Sjkim *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
118167802Sjkim *              Only a 32-bit physical address is necessary.
11978986Smsmith *
120167802Sjkim * NOTE2:       This function is always available, regardless of the
121167802Sjkim *              initialization state of the rest of ACPI.
12278986Smsmith *
12378986Smsmith ******************************************************************************/
12467754Smsmith
12578986SmsmithACPI_STATUS
126167802SjkimAcpiFindRootPointer (
127193267Sjkim    ACPI_SIZE               *TableAddress)
12878986Smsmith{
129167802Sjkim    UINT8                   *TablePtr;
130167802Sjkim    UINT8                   *MemRover;
131167802Sjkim    UINT32                  PhysicalAddress;
13278986Smsmith
13378986Smsmith
134167802Sjkim    ACPI_FUNCTION_TRACE (AcpiFindRootPointer);
13578986Smsmith
13678986Smsmith
137167802Sjkim    /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
13867754Smsmith
139167802Sjkim    TablePtr = AcpiOsMapMemory (
140167802Sjkim                (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION,
141167802Sjkim                ACPI_EBDA_PTR_LENGTH);
142167802Sjkim    if (!TablePtr)
14384491Smsmith    {
144167802Sjkim        ACPI_ERROR ((AE_INFO,
145204773Sjkim            "Could not map memory at 0x%8.8X for length %u",
146167802Sjkim            ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
14767754Smsmith
148138287Smarks        return_ACPI_STATUS (AE_NO_MEMORY);
149138287Smarks    }
150138287Smarks
151167802Sjkim    ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr);
15267754Smsmith
153167802Sjkim    /* Convert segment part to physical address */
15467754Smsmith
155167802Sjkim    PhysicalAddress <<= 4;
156167802Sjkim    AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH);
157138287Smarks
158167802Sjkim    /* EBDA present? */
159138287Smarks
160167802Sjkim    if (PhysicalAddress > 0x400)
161138287Smarks    {
162151937Sjkim        /*
163167802Sjkim         * 1b) Search EBDA paragraphs (EBDA is required to be a
164167802Sjkim         *     minimum of 1K length)
165151937Sjkim         */
166167802Sjkim        TablePtr = AcpiOsMapMemory (
167193267Sjkim                    (ACPI_PHYSICAL_ADDRESS) PhysicalAddress,
168167802Sjkim                    ACPI_EBDA_WINDOW_SIZE);
169167802Sjkim        if (!TablePtr)
17078986Smsmith        {
171167802Sjkim            ACPI_ERROR ((AE_INFO,
172204773Sjkim                "Could not map memory at 0x%8.8X for length %u",
173167802Sjkim                PhysicalAddress, ACPI_EBDA_WINDOW_SIZE));
17467754Smsmith
175167802Sjkim            return_ACPI_STATUS (AE_NO_MEMORY);
17678986Smsmith        }
17778986Smsmith
178167802Sjkim        MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE);
179167802Sjkim        AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE);
18078986Smsmith
181167802Sjkim        if (MemRover)
18278986Smsmith        {
183167802Sjkim            /* Return the physical address */
18478986Smsmith
185167802Sjkim            PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr);
18678986Smsmith
187167802Sjkim            *TableAddress = PhysicalAddress;
188167802Sjkim            return_ACPI_STATUS (AE_OK);
18978986Smsmith        }
19067754Smsmith    }
19167754Smsmith
192167802Sjkim    /*
193167802Sjkim     * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
194167802Sjkim     */
195167802Sjkim    TablePtr = AcpiOsMapMemory (
196167802Sjkim                (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE,
197167802Sjkim                ACPI_HI_RSDP_WINDOW_SIZE);
19867754Smsmith
199167802Sjkim    if (!TablePtr)
200151937Sjkim    {
201167802Sjkim        ACPI_ERROR ((AE_INFO,
202204773Sjkim            "Could not map memory at 0x%8.8X for length %u",
203167802Sjkim            ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
204138287Smarks
205167802Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
206138287Smarks    }
20767754Smsmith
208167802Sjkim    MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE);
209167802Sjkim    AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE);
21067754Smsmith
211167802Sjkim    if (MemRover)
212167802Sjkim    {
213167802Sjkim        /* Return the physical address */
21491116Smsmith
215167802Sjkim        PhysicalAddress = (UINT32)
216167802Sjkim            (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr));
21791116Smsmith
218167802Sjkim        *TableAddress = PhysicalAddress;
219167802Sjkim        return_ACPI_STATUS (AE_OK);
220167802Sjkim    }
22191116Smsmith
222167802Sjkim    /* A valid RSDP was not found */
22391116Smsmith
224238381Sjkim    ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found"));
225167802Sjkim    return_ACPI_STATUS (AE_NOT_FOUND);
226167802Sjkim}
22791116Smsmith
228167802SjkimACPI_EXPORT_SYMBOL (AcpiFindRootPointer)
22991116Smsmith
23091116Smsmith
23191116Smsmith/*******************************************************************************
23291116Smsmith *
23391116Smsmith * FUNCTION:    AcpiTbScanMemoryForRsdp
23491116Smsmith *
23591116Smsmith * PARAMETERS:  StartAddress        - Starting pointer for search
23691116Smsmith *              Length              - Maximum length to search
23791116Smsmith *
23891116Smsmith * RETURN:      Pointer to the RSDP if found, otherwise NULL.
23991116Smsmith *
24091116Smsmith * DESCRIPTION: Search a block of memory for the RSDP signature
24191116Smsmith *
24291116Smsmith ******************************************************************************/
24391116Smsmith
244252279SjkimUINT8 *
24591116SmsmithAcpiTbScanMemoryForRsdp (
24691116Smsmith    UINT8                   *StartAddress,
24791116Smsmith    UINT32                  Length)
24891116Smsmith{
249151937Sjkim    ACPI_STATUS             Status;
25091116Smsmith    UINT8                   *MemRover;
251138287Smarks    UINT8                   *EndAddress;
25291116Smsmith
25391116Smsmith
254167802Sjkim    ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp);
25591116Smsmith
25691116Smsmith
257138287Smarks    EndAddress = StartAddress + Length;
25891116Smsmith
259138287Smarks    /* Search from given start address for the requested length */
260138287Smarks
261138287Smarks    for (MemRover = StartAddress; MemRover < EndAddress;
262138287Smarks         MemRover += ACPI_RSDP_SCAN_STEP)
26391116Smsmith    {
264151937Sjkim        /* The RSDP signature and checksum must both be correct */
26591116Smsmith
266167802Sjkim        Status = AcpiTbValidateRsdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover));
267151937Sjkim        if (ACPI_SUCCESS (Status))
26891116Smsmith        {
269151937Sjkim            /* Sig and checksum valid, we have found a real RSDP */
27091116Smsmith
27191116Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
272138287Smarks                "RSDP located at physical address %p\n", MemRover));
27391116Smsmith            return_PTR (MemRover);
27491116Smsmith        }
275138287Smarks
276151937Sjkim        /* No sig match or bad checksum, keep searching */
27791116Smsmith    }
27891116Smsmith
27991116Smsmith    /* Searched entire block, no RSDP was found */
28091116Smsmith
281138287Smarks    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
282151937Sjkim        "Searched entire block from %p, valid RSDP was not found\n",
283151937Sjkim        StartAddress));
28491116Smsmith    return_PTR (NULL);
28591116Smsmith}
286