Blame view

drivers/acpi/acpica/tbxfroot.c 8.18 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /******************************************************************************
   *
   * Module Name: tbxfroot - Find the root ACPI table (RSDT)
   *
   *****************************************************************************/
  
  /*
75a44ce00   Len Brown   ACPICA: update In...
8
   * Copyright (C) 2000 - 2008, Intel Corp.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   *    substantially similar to the "NO WARRANTY" disclaimer below
   *    ("Disclaimer") and any redistribution must be conditioned upon
   *    including a substantially similar Disclaimer requirement for further
   *    binary redistribution.
   * 3. Neither the names of the above-listed copyright holders nor the names
   *    of any contributors may be used to endorse or promote products derived
   *    from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * NO WARRANTY
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  #include <acpi/acpi.h>
e2f7a7772   Len Brown   ACPICA: hide priv...
44
45
  #include "accommon.h"
  #include "actables.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  #define _COMPONENT          ACPI_TABLES
4be44fcd3   Len Brown   [ACPI] Lindent al...
48
  ACPI_MODULE_NAME("tbxfroot")
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

44f6c0124   Robert Moore   ACPICA 20050408 f...
50
  /* Local prototypes */
4be44fcd3   Len Brown   [ACPI] Lindent al...
51
  static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

f3d2e7865   Bob Moore   ACPICA: Implement...
53
  static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  /*******************************************************************************
   *
f9f4601f3   Robert Moore   ACPICA 20050708 f...
56
57
   * FUNCTION:    acpi_tb_validate_rsdp
   *
f3d2e7865   Bob Moore   ACPICA: Implement...
58
   * PARAMETERS:  Rsdp                - Pointer to unvalidated RSDP
f9f4601f3   Robert Moore   ACPICA 20050708 f...
59
60
61
62
63
64
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Validate the RSDP (ptr)
   *
   ******************************************************************************/
f3d2e7865   Bob Moore   ACPICA: Implement...
65
  static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
f9f4601f3   Robert Moore   ACPICA 20050708 f...
66
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
67
  	ACPI_FUNCTION_ENTRY();
f9f4601f3   Robert Moore   ACPICA 20050708 f...
68
69
  
  	/*
f3d2e7865   Bob Moore   ACPICA: Implement...
70
71
72
73
  	 * The signature and checksum must both be correct
  	 *
  	 * Note: Sometimes there exists more than one RSDP in memory; the valid
  	 * RSDP has a valid checksum, all others have an invalid checksum.
f9f4601f3   Robert Moore   ACPICA 20050708 f...
74
  	 */
ec41f193e   Bob Moore   ACPICA: Formattin...
75
76
  	if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP,
  			 sizeof(ACPI_SIG_RSDP) - 1) != 0) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
77

f9f4601f3   Robert Moore   ACPICA 20050708 f...
78
79
80
81
82
83
  		/* Nope, BAD Signature */
  
  		return (AE_BAD_SIGNATURE);
  	}
  
  	/* Check the standard checksum */
f3d2e7865   Bob Moore   ACPICA: Implement...
84
  	if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
f9f4601f3   Robert Moore   ACPICA 20050708 f...
85
86
87
88
89
90
  		return (AE_BAD_CHECKSUM);
  	}
  
  	/* Check extended checksum if table version >= 2 */
  
  	if ((rsdp->revision >= 2) &&
f3d2e7865   Bob Moore   ACPICA: Implement...
91
  	    (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
f9f4601f3   Robert Moore   ACPICA 20050708 f...
92
93
94
95
96
  		return (AE_BAD_CHECKSUM);
  	}
  
  	return (AE_OK);
  }
f9f4601f3   Robert Moore   ACPICA 20050708 f...
97
98
  /*******************************************************************************
   *
239665a3b   Len Brown   ACPI: tables: com...
99
   * FUNCTION:    acpi_find_root_pointer
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
   *
f3d2e7865   Bob Moore   ACPICA: Implement...
101
   * PARAMETERS:  table_address           - Where the table pointer is returned
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
   *
f3d2e7865   Bob Moore   ACPICA: Implement...
103
   * RETURN:      Status, RSDP physical address
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
   *
f3d2e7865   Bob Moore   ACPICA: Implement...
105
106
   * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
   *              pointer structure.  If it is found, set *RSDP to point to it.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
   *
f3d2e7865   Bob Moore   ACPICA: Implement...
108
109
110
   * NOTE1:       The RSDP must be either in the first 1_k of the Extended
   *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
   *              Only a 32-bit physical address is necessary.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
   *
f3d2e7865   Bob Moore   ACPICA: Implement...
112
113
   * NOTE2:       This function is always available, regardless of the
   *              initialization state of the rest of ACPI.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
   *
   ******************************************************************************/
67a119f99   Bob Moore   ACPICA: Eliminate...
116
  acpi_status acpi_find_root_pointer(acpi_size *table_address)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  {
f3d2e7865   Bob Moore   ACPICA: Implement...
118
119
120
  	u8 *table_ptr;
  	u8 *mem_rover;
  	u32 physical_address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

f3d2e7865   Bob Moore   ACPICA: Implement...
122
  	ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123

f3d2e7865   Bob Moore   ACPICA: Implement...
124
  	/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125

f3d2e7865   Bob Moore   ACPICA: Implement...
126
127
128
129
130
131
132
  	table_ptr = acpi_os_map_memory((acpi_physical_address)
  				       ACPI_EBDA_PTR_LOCATION,
  				       ACPI_EBDA_PTR_LENGTH);
  	if (!table_ptr) {
  		ACPI_ERROR((AE_INFO,
  			    "Could not map memory at %8.8X for length %X",
  			    ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133

4be44fcd3   Len Brown   [ACPI] Lindent al...
134
  		return_ACPI_STATUS(AE_NO_MEMORY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  	}
f3d2e7865   Bob Moore   ACPICA: Implement...
136
  	ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

f3d2e7865   Bob Moore   ACPICA: Implement...
138
  	/* Convert segment part to physical address */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

f3d2e7865   Bob Moore   ACPICA: Implement...
140
141
  	physical_address <<= 4;
  	acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

f3d2e7865   Bob Moore   ACPICA: Implement...
143
  	/* EBDA present? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

f3d2e7865   Bob Moore   ACPICA: Implement...
145
  	if (physical_address > 0x400) {
73459f73e   Robert Moore   ACPICA 20050617-0...
146
  		/*
f3d2e7865   Bob Moore   ACPICA: Implement...
147
148
  		 * 1b) Search EBDA paragraphs (EBDA is required to be a
  		 *     minimum of 1_k length)
73459f73e   Robert Moore   ACPICA 20050617-0...
149
  		 */
67a119f99   Bob Moore   ACPICA: Eliminate...
150
  		table_ptr = acpi_os_map_memory((acpi_physical_address)
f3d2e7865   Bob Moore   ACPICA: Implement...
151
152
153
154
155
156
  					       physical_address,
  					       ACPI_EBDA_WINDOW_SIZE);
  		if (!table_ptr) {
  			ACPI_ERROR((AE_INFO,
  				    "Could not map memory at %8.8X for length %X",
  				    physical_address, ACPI_EBDA_WINDOW_SIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

f3d2e7865   Bob Moore   ACPICA: Implement...
158
  			return_ACPI_STATUS(AE_NO_MEMORY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  		}
f3d2e7865   Bob Moore   ACPICA: Implement...
160
161
162
163
  		mem_rover =
  		    acpi_tb_scan_memory_for_rsdp(table_ptr,
  						 ACPI_EBDA_WINDOW_SIZE);
  		acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

f3d2e7865   Bob Moore   ACPICA: Implement...
165
  		if (mem_rover) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
166

f3d2e7865   Bob Moore   ACPICA: Implement...
167
  			/* Return the physical address */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

f3d2e7865   Bob Moore   ACPICA: Implement...
169
170
  			physical_address +=
  			    (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171

f3d2e7865   Bob Moore   ACPICA: Implement...
172
173
  			*table_address = physical_address;
  			return_ACPI_STATUS(AE_OK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
  		}
  	}
f3d2e7865   Bob Moore   ACPICA: Implement...
176
177
178
179
180
181
  	/*
  	 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
  	 */
  	table_ptr = acpi_os_map_memory((acpi_physical_address)
  				       ACPI_HI_RSDP_WINDOW_BASE,
  				       ACPI_HI_RSDP_WINDOW_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182

f3d2e7865   Bob Moore   ACPICA: Implement...
183
184
185
186
187
  	if (!table_ptr) {
  		ACPI_ERROR((AE_INFO,
  			    "Could not map memory at %8.8X for length %X",
  			    ACPI_HI_RSDP_WINDOW_BASE,
  			    ACPI_HI_RSDP_WINDOW_SIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188

f3d2e7865   Bob Moore   ACPICA: Implement...
189
  		return_ACPI_STATUS(AE_NO_MEMORY);
88ac00f5a   Robert Moore   ACPICA 20050526 f...
190
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191

f3d2e7865   Bob Moore   ACPICA: Implement...
192
193
194
  	mem_rover =
  	    acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
  	acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

f3d2e7865   Bob Moore   ACPICA: Implement...
196
  	if (mem_rover) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

f3d2e7865   Bob Moore   ACPICA: Implement...
198
  		/* Return the physical address */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199

f3d2e7865   Bob Moore   ACPICA: Implement...
200
201
202
  		physical_address = (u32)
  		    (ACPI_HI_RSDP_WINDOW_BASE +
  		     ACPI_PTR_DIFF(mem_rover, table_ptr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203

f3d2e7865   Bob Moore   ACPICA: Implement...
204
205
  		*table_address = physical_address;
  		return_ACPI_STATUS(AE_OK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  	}
f3d2e7865   Bob Moore   ACPICA: Implement...
207
208
209
210
  	/* A valid RSDP was not found */
  
  	ACPI_ERROR((AE_INFO, "A valid RSDP was not found"));
  	return_ACPI_STATUS(AE_NOT_FOUND);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
215
216
217
218
219
220
221
222
223
  /*******************************************************************************
   *
   * FUNCTION:    acpi_tb_scan_memory_for_rsdp
   *
   * PARAMETERS:  start_address       - Starting pointer for search
   *              Length              - Maximum length to search
   *
   * RETURN:      Pointer to the RSDP if found, otherwise NULL.
   *
   * DESCRIPTION: Search a block of memory for the RSDP signature
   *
   ******************************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
224
  static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
226
227
228
  	acpi_status status;
  	u8 *mem_rover;
  	u8 *end_address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229

b229cf92e   Bob Moore   ACPI: ACPICA 2006...
230
  	ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
  
  	end_address = start_address + length;
  
  	/* Search from given start address for the requested length */
  
  	for (mem_rover = start_address; mem_rover < end_address;
4be44fcd3   Len Brown   [ACPI] Lindent al...
237
  	     mem_rover += ACPI_RSDP_SCAN_STEP) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
238

f9f4601f3   Robert Moore   ACPICA 20050708 f...
239
  		/* The RSDP signature and checksum must both be correct */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240

4be44fcd3   Len Brown   [ACPI] Lindent al...
241
242
  		status =
  		    acpi_tb_validate_rsdp(ACPI_CAST_PTR
f3d2e7865   Bob Moore   ACPICA: Implement...
243
  					  (struct acpi_table_rsdp, mem_rover));
4be44fcd3   Len Brown   [ACPI] Lindent al...
244
  		if (ACPI_SUCCESS(status)) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
245

f9f4601f3   Robert Moore   ACPICA 20050708 f...
246
  			/* Sig and checksum valid, we have found a real RSDP */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247

4be44fcd3   Len Brown   [ACPI] Lindent al...
248
249
250
251
252
  			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  					  "RSDP located at physical address %p
  ",
  					  mem_rover));
  			return_PTR(mem_rover);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  		}
f9f4601f3   Robert Moore   ACPICA 20050708 f...
254
  		/* No sig match or bad checksum, keep searching */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
  	}
  
  	/* Searched entire block, no RSDP was found */
4be44fcd3   Len Brown   [ACPI] Lindent al...
258
259
260
261
262
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  			  "Searched entire block from %p, valid RSDP was not found
  ",
  			  start_address));
  	return_PTR(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  }