~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/drivers/acpi/tables/tbxfroot.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 *
 
3
 * Module Name: tbxfroot - Find the root ACPI table (RSDT)
 
4
 *
 
5
 *****************************************************************************/
 
6
 
 
7
/*
 
8
 * Copyright (C) 2000 - 2008, 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 <xen/config.h>
 
45
#include <xen/init.h>
 
46
#include <acpi/acpi.h>
 
47
#include <acpi/actables.h>
 
48
 
 
49
#define _COMPONENT          ACPI_TABLES
 
50
ACPI_MODULE_NAME("tbxfroot")
 
51
 
 
52
/* Local prototypes */
 
53
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
 
54
 
 
55
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
 
56
 
 
57
/*******************************************************************************
 
58
 *
 
59
 * FUNCTION:    acpi_tb_validate_rsdp
 
60
 *
 
61
 * PARAMETERS:  Rsdp                - Pointer to unvalidated RSDP
 
62
 *
 
63
 * RETURN:      Status
 
64
 *
 
65
 * DESCRIPTION: Validate the RSDP (ptr)
 
66
 *
 
67
 ******************************************************************************/
 
68
 
 
69
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
 
70
{
 
71
        ACPI_FUNCTION_ENTRY();
 
72
 
 
73
        /*
 
74
         * The signature and checksum must both be correct
 
75
         *
 
76
         * Note: Sometimes there exists more than one RSDP in memory; the valid
 
77
         * RSDP has a valid checksum, all others have an invalid checksum.
 
78
         */
 
79
        if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)
 
80
            != 0) {
 
81
 
 
82
                /* Nope, BAD Signature */
 
83
 
 
84
                return (AE_BAD_SIGNATURE);
 
85
        }
 
86
 
 
87
        /* Check the standard checksum */
 
88
 
 
89
        if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
 
90
                return (AE_BAD_CHECKSUM);
 
91
        }
 
92
 
 
93
        /* Check extended checksum if table version >= 2 */
 
94
 
 
95
        if ((rsdp->revision >= 2) &&
 
96
            (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
 
97
                return (AE_BAD_CHECKSUM);
 
98
        }
 
99
 
 
100
        return (AE_OK);
 
101
}
 
102
 
 
103
/*******************************************************************************
 
104
 *
 
105
 * FUNCTION:    acpi_find_root_pointer
 
106
 *
 
107
 * PARAMETERS:  table_address           - Where the table pointer is returned
 
108
 *
 
109
 * RETURN:      Status, RSDP physical address
 
110
 *
 
111
 * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
 
112
 *              pointer structure.  If it is found, set *RSDP to point to it.
 
113
 *
 
114
 * NOTE1:       The RSDP must be either in the first 1_k of the Extended
 
115
 *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
 
116
 *              Only a 32-bit physical address is necessary.
 
117
 *
 
118
 * NOTE2:       This function is always available, regardless of the
 
119
 *              initialization state of the rest of ACPI.
 
120
 *
 
121
 ******************************************************************************/
 
122
 
 
123
acpi_status __init acpi_find_root_pointer(acpi_native_uint * table_address)
 
124
{
 
125
        u8 *table_ptr;
 
126
        u8 *mem_rover;
 
127
        u32 physical_address;
 
128
 
 
129
        ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
 
130
 
 
131
        /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
 
132
 
 
133
        table_ptr = acpi_os_map_memory((acpi_physical_address)
 
134
                                       ACPI_EBDA_PTR_LOCATION,
 
135
                                       ACPI_EBDA_PTR_LENGTH);
 
136
        if (!table_ptr) {
 
137
                ACPI_ERROR((AE_INFO,
 
138
                            "Could not map memory at %8.8X for length %X",
 
139
                            ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
 
140
 
 
141
                return_ACPI_STATUS(AE_NO_MEMORY);
 
142
        }
 
143
 
 
144
        ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
 
145
 
 
146
        /* Convert segment part to physical address */
 
147
 
 
148
        physical_address <<= 4;
 
149
        acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
 
150
 
 
151
        /* EBDA present? */
 
152
 
 
153
        if (physical_address > 0x400) {
 
154
                /*
 
155
                 * 1b) Search EBDA paragraphs (EBDA is required to be a
 
156
                 *     minimum of 1_k length)
 
157
                 */
 
158
                table_ptr = acpi_os_map_memory((acpi_native_uint)
 
159
                                               physical_address,
 
160
                                               ACPI_EBDA_WINDOW_SIZE);
 
161
                if (!table_ptr) {
 
162
                        ACPI_ERROR((AE_INFO,
 
163
                                    "Could not map memory at %8.8X for length %X",
 
164
                                    physical_address, ACPI_EBDA_WINDOW_SIZE));
 
165
 
 
166
                        return_ACPI_STATUS(AE_NO_MEMORY);
 
167
                }
 
168
 
 
169
                mem_rover =
 
170
                    acpi_tb_scan_memory_for_rsdp(table_ptr,
 
171
                                                 ACPI_EBDA_WINDOW_SIZE);
 
172
                acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
 
173
 
 
174
                if (mem_rover) {
 
175
 
 
176
                        /* Return the physical address */
 
177
 
 
178
                        physical_address +=
 
179
                            (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 
180
 
 
181
                        *table_address = physical_address;
 
182
                        return_ACPI_STATUS(AE_OK);
 
183
                }
 
184
        }
 
185
 
 
186
        /*
 
187
         * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 
188
         */
 
189
        table_ptr = acpi_os_map_memory((acpi_physical_address)
 
190
                                       ACPI_HI_RSDP_WINDOW_BASE,
 
191
                                       ACPI_HI_RSDP_WINDOW_SIZE);
 
192
 
 
193
        if (!table_ptr) {
 
194
                ACPI_ERROR((AE_INFO,
 
195
                            "Could not map memory at %8.8X for length %X",
 
196
                            ACPI_HI_RSDP_WINDOW_BASE,
 
197
                            ACPI_HI_RSDP_WINDOW_SIZE));
 
198
 
 
199
                return_ACPI_STATUS(AE_NO_MEMORY);
 
200
        }
 
201
 
 
202
        mem_rover =
 
203
            acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 
204
        acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 
205
 
 
206
        if (mem_rover) {
 
207
 
 
208
                /* Return the physical address */
 
209
 
 
210
                physical_address = (u32)
 
211
                    (ACPI_HI_RSDP_WINDOW_BASE +
 
212
                     ACPI_PTR_DIFF(mem_rover, table_ptr));
 
213
 
 
214
                *table_address = physical_address;
 
215
                return_ACPI_STATUS(AE_OK);
 
216
        }
 
217
 
 
218
        /* A valid RSDP was not found */
 
219
 
 
220
        ACPI_ERROR((AE_INFO, "A valid RSDP was not found"));
 
221
        return_ACPI_STATUS(AE_NOT_FOUND);
 
222
}
 
223
 
 
224
/*******************************************************************************
 
225
 *
 
226
 * FUNCTION:    acpi_tb_scan_memory_for_rsdp
 
227
 *
 
228
 * PARAMETERS:  start_address       - Starting pointer for search
 
229
 *              Length              - Maximum length to search
 
230
 *
 
231
 * RETURN:      Pointer to the RSDP if found, otherwise NULL.
 
232
 *
 
233
 * DESCRIPTION: Search a block of memory for the RSDP signature
 
234
 *
 
235
 ******************************************************************************/
 
236
static u8 *__init acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
 
237
{
 
238
        acpi_status status;
 
239
        u8 *mem_rover;
 
240
        u8 *end_address;
 
241
 
 
242
        ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
 
243
 
 
244
        end_address = start_address + length;
 
245
 
 
246
        /* Search from given start address for the requested length */
 
247
 
 
248
        for (mem_rover = start_address; mem_rover < end_address;
 
249
             mem_rover += ACPI_RSDP_SCAN_STEP) {
 
250
 
 
251
                /* The RSDP signature and checksum must both be correct */
 
252
 
 
253
                status =
 
254
                    acpi_tb_validate_rsdp(ACPI_CAST_PTR
 
255
                                          (struct acpi_table_rsdp, mem_rover));
 
256
                if (ACPI_SUCCESS(status)) {
 
257
 
 
258
                        /* Sig and checksum valid, we have found a real RSDP */
 
259
 
 
260
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 
261
                                          "RSDP located at physical address %p\n",
 
262
                                          mem_rover));
 
263
                        return_PTR(mem_rover);
 
264
                }
 
265
 
 
266
                /* No sig match or bad checksum, keep searching */
 
267
        }
 
268
 
 
269
        /* Searched entire block, no RSDP was found */
 
270
 
 
271
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 
272
                          "Searched entire block from %p, valid RSDP was not found\n",
 
273
                          start_address));
 
274
        return_PTR(NULL);
 
275
}