@@ -107,3 +107,80 @@ static acpi_physical_address efi_get_rsdp_addr(void)
107
107
#endif
108
108
return rsdp_addr ;
109
109
}
110
+
111
+ static u8 compute_checksum (u8 * buffer , u32 length )
112
+ {
113
+ u8 * end = buffer + length ;
114
+ u8 sum = 0 ;
115
+
116
+ while (buffer < end )
117
+ sum += * (buffer ++ );
118
+
119
+ return sum ;
120
+ }
121
+
122
+ /* Search a block of memory for the RSDP signature. */
123
+ static u8 * scan_mem_for_rsdp (u8 * start , u32 length )
124
+ {
125
+ struct acpi_table_rsdp * rsdp ;
126
+ u8 * address , * end ;
127
+
128
+ end = start + length ;
129
+
130
+ /* Search from given start address for the requested length */
131
+ for (address = start ; address < end ; address += ACPI_RSDP_SCAN_STEP ) {
132
+ /*
133
+ * Both RSDP signature and checksum must be correct.
134
+ * Note: Sometimes there exists more than one RSDP in memory;
135
+ * the valid RSDP has a valid checksum, all others have an
136
+ * invalid checksum.
137
+ */
138
+ rsdp = (struct acpi_table_rsdp * )address ;
139
+
140
+ /* BAD Signature */
141
+ if (!ACPI_VALIDATE_RSDP_SIG (rsdp -> signature ))
142
+ continue ;
143
+
144
+ /* Check the standard checksum */
145
+ if (compute_checksum ((u8 * )rsdp , ACPI_RSDP_CHECKSUM_LENGTH ))
146
+ continue ;
147
+
148
+ /* Check extended checksum if table version >= 2 */
149
+ if ((rsdp -> revision >= 2 ) &&
150
+ (compute_checksum ((u8 * )rsdp , ACPI_RSDP_XCHECKSUM_LENGTH )))
151
+ continue ;
152
+
153
+ /* Signature and checksum valid, we have found a real RSDP */
154
+ return address ;
155
+ }
156
+ return NULL ;
157
+ }
158
+
159
+ /* Search RSDP address in EBDA. */
160
+ static acpi_physical_address bios_get_rsdp_addr (void )
161
+ {
162
+ unsigned long address ;
163
+ u8 * rsdp ;
164
+
165
+ /* Get the location of the Extended BIOS Data Area (EBDA) */
166
+ address = * (u16 * )ACPI_EBDA_PTR_LOCATION ;
167
+ address <<= 4 ;
168
+
169
+ /*
170
+ * Search EBDA paragraphs (EBDA is required to be a minimum of
171
+ * 1K length)
172
+ */
173
+ if (address > 0x400 ) {
174
+ rsdp = scan_mem_for_rsdp ((u8 * )address , ACPI_EBDA_WINDOW_SIZE );
175
+ if (rsdp )
176
+ return (acpi_physical_address )(unsigned long )rsdp ;
177
+ }
178
+
179
+ /* Search upper memory: 16-byte boundaries in E0000h-FFFFFh */
180
+ rsdp = scan_mem_for_rsdp ((u8 * ) ACPI_HI_RSDP_WINDOW_BASE ,
181
+ ACPI_HI_RSDP_WINDOW_SIZE );
182
+ if (rsdp )
183
+ return (acpi_physical_address )(unsigned long )rsdp ;
184
+
185
+ return 0 ;
186
+ }
0 commit comments