Bug Summary

File:src/add-ons/kernel/bus_managers/pci/arch/x86/pci_acpi.cpp
Location:line 128, column 12
Description:Access to field 'length' results in a dereference of a null pointer (loaded from variable 'rsdt')

Annotated Source Code

1/*
2 * Copyright 2011, Rene Gollent, rene@gollent.com.
3 * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
4 * Copyright 2007, Michael Lotz, mmlr@mlotz.ch
5 * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de.
6 * Distributed under the terms of the MIT License.
7 *
8 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
9 * Distributed under the terms of the NewOS License.
10*/
11
12
13#include "pci_acpi.h"
14
15#include <string.h>
16
17#include <KernelExport.h>
18
19#include <arch/x86/arch_acpi.h>
20
21
22//#define TRACE_ACPI
23#ifdef TRACE_ACPI
24# define TRACE(x); dprintf x
25#else
26# define TRACE(x); ;
27#endif
28
29static struct scan_spots_struct acpi_scan_spots[] = {
30 { 0x0, 0x1000, 0x1000 },
31 { 0x9f000, 0x10000, 0x1000 },
32 { 0xe0000, 0x110000, 0x20000 },
33 { 0xfd000, 0xfe000, 0x1000},
34 { 0, 0, 0 }
35};
36
37static acpi_descriptor_header* sAcpiRsdt; // System Description Table
38static acpi_descriptor_header* sAcpiXsdt; // Extended System Description Table
39static int32 sNumEntries = -1;
40
41
42static status_t
43acpi_validate_rsdp(acpi_rsdp* rsdp)
44{
45 const char* data = (const char*)rsdp;
46 unsigned char checksum = 0;
47 for (uint32 i = 0; i < sizeof(acpi_rsdp_legacy); i++)
48 checksum += data[i];
49
50 if ((checksum & 0xff) != 0) {
51 TRACE(("acpi: rsdp failed basic checksum\n"));;
52 return B_BAD_DATA((-2147483647 - 1) + 16);
53 }
54
55 // for ACPI 2.0+ we need to also validate the extended checksum
56 if (rsdp->revision > 0) {
57 for (uint32 i = sizeof(acpi_rsdp_legacy);
58 i < sizeof(acpi_rsdp_extended); i++) {
59 checksum += data[i];
60 }
61
62 if ((checksum & 0xff) != 0) {
63 TRACE(("acpi: rsdp failed extended checksum\n"));;
64 return B_BAD_DATA((-2147483647 - 1) + 16);
65 }
66 }
67
68 return B_OK((int)0);
69}
70
71
72static status_t
73acpi_validate_rsdt(acpi_descriptor_header* rsdt)
74{
75 const char* data = (const char*)rsdt;
76 unsigned char checksum = 0;
77 for (uint32 i = 0; i < rsdt->length; i++)
78 checksum += data[i];
79
80 return checksum == 0 ? B_OK((int)0) : B_BAD_DATA((-2147483647 - 1) + 16);
81}
82
83
84static status_t
85acpi_check_rsdt(acpi_rsdp* rsdp)
86{
87 if (acpi_validate_rsdp(rsdp) != B_OK((int)0))
8
Taking false branch
88 return B_BAD_DATA((-2147483647 - 1) + 16);
89
90 bool usingXsdt = false;
91
92 TRACE(("acpi: found rsdp at %p oem id: %.6s, rev %d\n",;
93 rsdp, rsdp->oem_id, rsdp->revision));;
94 TRACE(("acpi: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address));;
95
96 uint32 length = 0;
97 acpi_descriptor_header* rsdt = NULL__null;
98 area_id rsdtArea = -1;
99 if (rsdp->revision > 0) {
9
Taking false branch
100 length = rsdp->xsdt_length;
101 rsdtArea = map_physical_memory("rsdt acpi",
102 (uint32)rsdp->xsdt_address, rsdp->xsdt_length, B_ANY_KERNEL_ADDRESS4,
103 B_KERNEL_READ_AREA16, (void **)&rsdt);
104 if (rsdt != NULL__null
105 && strncmp(rsdt->signature, ACPI_XSDT_SIGNATURE"XSDT", 4) != 0) {
106 delete_area(rsdtArea);
107 rsdt = NULL__null;
108 TRACE(("acpi: invalid extended system description table\n"));;
109 } else
110 usingXsdt = true;
111 }
112
113 // if we're ACPI v1 or we fail to map the XSDT for some reason,
114 // attempt to use the RSDT instead.
115 if (rsdt == NULL__null) {
10
Taking true branch
116 // map and validate the root system description table
117 rsdtArea = map_physical_memory("rsdt acpi",
11
Value assigned to 'rsdt'
118 rsdp->rsdt_address, sizeof(acpi_descriptor_header),
119 B_ANY_KERNEL_ADDRESS4, B_KERNEL_READ_AREA16, (void **)&rsdt);
120 if (rsdt != NULL__null
12
Assuming pointer value is null
121 && strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE"RSDT", 4) != 0) {
122 delete_area(rsdtArea);
123 rsdt = NULL__null;
124 TRACE(("acpi: invalid root system description table\n"));;
125 return B_ERROR(-1);
126 }
127
128 length = rsdt->length;
13
Access to field 'length' results in a dereference of a null pointer (loaded from variable 'rsdt')
129 // Map the whole table, not just the header
130 TRACE(("acpi: rsdt length: %lu\n", length));;
131 delete_area(rsdtArea);
132 rsdtArea = map_physical_memory("rsdt acpi",
133 rsdp->rsdt_address, length, B_ANY_KERNEL_ADDRESS4,
134 B_KERNEL_READ_AREA16, (void **)&rsdt);
135 }
136
137 if (rsdt != NULL__null) {
138 if (acpi_validate_rsdt(rsdt) != B_OK((int)0)) {
139 TRACE(("acpi: rsdt failed checksum validation\n"));;
140 delete_area(rsdtArea);
141 return B_ERROR(-1);
142 } else {
143 if (usingXsdt)
144 sAcpiXsdt = rsdt;
145 else
146 sAcpiRsdt = rsdt;
147 TRACE(("acpi: found valid %s at %p\n",;
148 usingXsdt ? ACPI_XSDT_SIGNATURE : ACPI_RSDT_SIGNATURE,;
149 rsdt));;
150 }
151 } else
152 return B_ERROR(-1);
153
154 return B_OK((int)0);
155}
156
157
158template<typename PointerType>
159acpi_descriptor_header*
160acpi_find_table_generic(const char* signature, acpi_descriptor_header* acpiSdt)
161{
162 if (acpiSdt == NULL__null)
163 return NULL__null;
164
165 if (sNumEntries == -1) {
166 // if using the xsdt, our entries are 64 bits wide.
167 sNumEntries = (acpiSdt->length
168 - sizeof(acpi_descriptor_header))
169 / sizeof(PointerType);
170 }
171
172 if (sNumEntries <= 0) {
173 TRACE(("acpi: root system description table is empty\n"));;
174 return NULL__null;
175 }
176
177 TRACE(("acpi: searching %ld entries for table '%.4s'\n", sNumEntries,;
178 signature));;
179
180 PointerType* pointer = (PointerType*)((uint8*)acpiSdt
181 + sizeof(acpi_descriptor_header));
182
183 acpi_descriptor_header* header = NULL__null;
184 area_id headerArea = -1;
185 for (int32 j = 0; j < sNumEntries; j++, pointer++) {
186 headerArea = map_physical_memory("acpi header", (uint32)*pointer,
187 sizeof(acpi_descriptor_header), B_ANY_KERNEL_ADDRESS4,
188 B_KERNEL_READ_AREA16, (void **)&header);
189
190 if (header == NULL__null
191 || strncmp(header->signature, signature, 4) != 0) {
192 // not interesting for us
193 TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n",;
194 signature, header != NULL ? header->signature : "null"));;
195
196 if (header != NULL__null) {
197 delete_area(headerArea);
198 header = NULL__null;
199 }
200
201 continue;
202 }
203
204 TRACE(("acpi: Found '%.4s' @ %p\n", signature, pointer));;
205 break;
206 }
207
208
209 if (header == NULL__null)
210 return NULL__null;
211
212 // Map the whole table, not just the header
213 uint32 length = header->length;
214 delete_area(headerArea);
215
216 headerArea = map_physical_memory("acpi table",
217 (uint32)*pointer, length, B_ANY_KERNEL_ADDRESS4,
218 B_KERNEL_READ_AREA16, (void **)&header);
219 return header;
220}
221
222
223void*
224acpi_find_table(const char* signature)
225{
226 if (sAcpiRsdt != NULL__null)
227 return acpi_find_table_generic<uint32>(signature, sAcpiRsdt);
228 else if (sAcpiXsdt != NULL__null)
229 return acpi_find_table_generic<uint64>(signature, sAcpiXsdt);
230
231 return NULL__null;
232}
233
234
235void
236acpi_init()
237{
238 // Try to find the ACPI RSDP.
239 for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) {
1
Loop condition is true. Entering loop body
240 acpi_rsdp* rsdp = NULL__null;
241
242 TRACE(("acpi_init: entry base 0x%lx, limit 0x%lx\n",;
243 acpi_scan_spots[i].start, acpi_scan_spots[i].stop));;
244
245 char* start = NULL__null;
246 area_id rsdpArea = map_physical_memory("acpi rsdp",
247 acpi_scan_spots[i].start, acpi_scan_spots[i].length,
248 B_ANY_KERNEL_ADDRESS4, B_KERNEL_READ_AREA16, (void **)&start);
249 if (rsdpArea < B_OK((int)0)) {
2
Assuming 'rsdpArea' is >= 0
3
Taking false branch
250 TRACE(("acpi_init: couldn't map %s\n", strerror(rsdpArea)));;
251 break;
252 }
253 for (char *pointer = start;
4
Loop condition is true. Entering loop body
6
Loop condition is false. Execution continues on line 263
254 (addr_t)pointer < (addr_t)start + acpi_scan_spots[i].length;
255 pointer += 16) {
256 if (strncmp(pointer, ACPI_RSDP_SIGNATURE"RSD PTR ", 8) == 0) {
5
Taking true branch
257 TRACE(("acpi_init: found ACPI RSDP signature at %p\n",;
258 pointer));;
259 rsdp = (acpi_rsdp*)pointer;
260 }
261 }
262
263 if (rsdp != NULL__null && acpi_check_rsdt(rsdp) == B_OK((int)0)) {
7
Calling 'acpi_check_rsdt'
264 delete_area(rsdpArea);
265 break;
266 }
267 delete_area(rsdpArea);
268 }
269
270}