1
2
3
4
5
6
7
8#include <acpi/acpi.h>
9#include "accommon.h"
10#include "acresrc.h"
11
12#define _COMPONENT ACPI_UTILITIES
13ACPI_MODULE_NAME("utresrc")
14
15
16
17
18
19const u8 acpi_gbl_resource_aml_sizes[] = {
20
21
22 0,
23 0,
24 0,
25 0,
26 ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
27 ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
28 ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
29 ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
30 ACPI_AML_SIZE_SMALL(struct aml_resource_io),
31 ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
32 ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
33 0,
34 0,
35 0,
36 ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
37 ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
38
39
40
41 0,
42 ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
43 ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
44 0,
45 ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
46 ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
47 ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
48 ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
49 ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
50 ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
51 ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
52 ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
53 ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
54 ACPI_AML_SIZE_LARGE(struct aml_resource_pin_function),
55 ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
56 ACPI_AML_SIZE_LARGE(struct aml_resource_pin_config),
57 ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group),
58 ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_function),
59 ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_config),
60};
61
62const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
63 0,
64 ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
65 ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
66 ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
67 ACPI_AML_SIZE_LARGE(struct aml_resource_csi2_serialbus),
68};
69
70
71
72
73
74
75
76static const u8 acpi_gbl_resource_types[] = {
77
78
79 0,
80 0,
81 0,
82 0,
83 ACPI_SMALL_VARIABLE_LENGTH,
84 ACPI_FIXED_LENGTH,
85 ACPI_SMALL_VARIABLE_LENGTH,
86 ACPI_FIXED_LENGTH,
87 ACPI_FIXED_LENGTH,
88 ACPI_FIXED_LENGTH,
89 ACPI_FIXED_LENGTH,
90 0,
91 0,
92 0,
93 ACPI_VARIABLE_LENGTH,
94 ACPI_FIXED_LENGTH,
95
96
97
98 0,
99 ACPI_FIXED_LENGTH,
100 ACPI_FIXED_LENGTH,
101 0,
102 ACPI_VARIABLE_LENGTH,
103 ACPI_FIXED_LENGTH,
104 ACPI_FIXED_LENGTH,
105 ACPI_VARIABLE_LENGTH,
106 ACPI_VARIABLE_LENGTH,
107 ACPI_VARIABLE_LENGTH,
108 ACPI_VARIABLE_LENGTH,
109 ACPI_FIXED_LENGTH,
110 ACPI_VARIABLE_LENGTH,
111 ACPI_VARIABLE_LENGTH,
112 ACPI_VARIABLE_LENGTH,
113 ACPI_VARIABLE_LENGTH,
114 ACPI_VARIABLE_LENGTH,
115 ACPI_VARIABLE_LENGTH,
116 ACPI_VARIABLE_LENGTH,
117};
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137acpi_status
138acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
139 u8 *aml,
140 acpi_size aml_length,
141 acpi_walk_aml_callback user_function, void **context)
142{
143 acpi_status status;
144 u8 *end_aml;
145 u8 resource_index;
146 u32 length;
147 u32 offset = 0;
148 u8 end_tag[2] = { 0x79, 0x00 };
149
150 ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
151
152
153
154 if (aml_length < sizeof(struct aml_resource_end_tag)) {
155 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
156 }
157
158
159
160 end_aml = aml + aml_length;
161
162
163
164 while (aml < end_aml) {
165
166
167
168 status =
169 acpi_ut_validate_resource(walk_state, aml, &resource_index);
170 if (ACPI_FAILURE(status)) {
171
172
173
174
175 return_ACPI_STATUS(status);
176 }
177
178
179
180 length = acpi_ut_get_descriptor_length(aml);
181
182
183
184 if (user_function) {
185 status =
186 user_function(aml, length, offset, resource_index,
187 context);
188 if (ACPI_FAILURE(status)) {
189 return_ACPI_STATUS(status);
190 }
191 }
192
193
194
195 if (acpi_ut_get_resource_type(aml) ==
196 ACPI_RESOURCE_NAME_END_TAG) {
197
198
199
200
201 if ((aml + 1) >= end_aml) {
202 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
203 }
204
205
206
207
208
209
210
211
212
213
214 if (!user_function) {
215 *context = aml;
216 }
217
218
219
220 return_ACPI_STATUS(AE_OK);
221 }
222
223 aml += length;
224 offset += length;
225 }
226
227
228
229 if (user_function) {
230
231
232
233 (void)acpi_ut_validate_resource(walk_state, end_tag,
234 &resource_index);
235 status =
236 user_function(end_tag, 2, offset, resource_index, context);
237 if (ACPI_FAILURE(status)) {
238 return_ACPI_STATUS(status);
239 }
240 }
241
242 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
243}
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262acpi_status
263acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
264 void *aml, u8 *return_index)
265{
266 union aml_resource *aml_resource;
267 u8 resource_type;
268 u8 resource_index;
269 acpi_rs_length resource_length;
270 acpi_rs_length minimum_resource_length;
271
272 ACPI_FUNCTION_ENTRY();
273
274
275
276
277 resource_type = ACPI_GET8(aml);
278
279
280
281
282
283 if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
284
285
286
287 if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
288 goto invalid_resource;
289 }
290
291
292
293
294
295 resource_index = (u8) (resource_type - 0x70);
296 } else {
297
298
299
300
301 resource_index = (u8)
302 ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
303 }
304
305
306
307
308
309 if (!acpi_gbl_resource_types[resource_index]) {
310 goto invalid_resource;
311 }
312
313
314
315
316
317 resource_length = acpi_ut_get_resource_length(aml);
318 minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
319
320
321
322 switch (acpi_gbl_resource_types[resource_index]) {
323 case ACPI_FIXED_LENGTH:
324
325
326
327 if (resource_length != minimum_resource_length) {
328 goto bad_resource_length;
329 }
330 break;
331
332 case ACPI_VARIABLE_LENGTH:
333
334
335
336 if (resource_length < minimum_resource_length) {
337 goto bad_resource_length;
338 }
339 break;
340
341 case ACPI_SMALL_VARIABLE_LENGTH:
342
343
344
345 if ((resource_length > minimum_resource_length) ||
346 (resource_length < (minimum_resource_length - 1))) {
347 goto bad_resource_length;
348 }
349 break;
350
351 default:
352
353
354
355 goto invalid_resource;
356 }
357
358 aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
359 if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
360
361
362
363 if ((aml_resource->common_serial_bus.type == 0) ||
364 (aml_resource->common_serial_bus.type >
365 AML_RESOURCE_MAX_SERIALBUSTYPE)) {
366 if (walk_state) {
367 ACPI_ERROR((AE_INFO,
368 "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
369 aml_resource->common_serial_bus.
370 type));
371 }
372 return (AE_AML_INVALID_RESOURCE_TYPE);
373 }
374 }
375
376
377
378 if (return_index) {
379 *return_index = resource_index;
380 }
381
382 return (AE_OK);
383
384invalid_resource:
385
386 if (walk_state) {
387 ACPI_ERROR((AE_INFO,
388 "Invalid/unsupported resource descriptor: Type 0x%2.2X",
389 resource_type));
390 }
391 return (AE_AML_INVALID_RESOURCE_TYPE);
392
393bad_resource_length:
394
395 if (walk_state) {
396 ACPI_ERROR((AE_INFO,
397 "Invalid resource descriptor length: Type "
398 "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
399 resource_type, resource_length,
400 minimum_resource_length));
401 }
402 return (AE_AML_BAD_RESOURCE_LENGTH);
403}
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419u8 acpi_ut_get_resource_type(void *aml)
420{
421 ACPI_FUNCTION_ENTRY();
422
423
424
425
426
427 if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
428
429
430
431 return (ACPI_GET8(aml));
432 } else {
433
434
435 return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
436 }
437}
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453u16 acpi_ut_get_resource_length(void *aml)
454{
455 acpi_rs_length resource_length;
456
457 ACPI_FUNCTION_ENTRY();
458
459
460
461
462
463 if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
464
465
466
467 ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
468
469 } else {
470
471
472 resource_length = (u16) (ACPI_GET8(aml) &
473 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
474 }
475
476 return (resource_length);
477}
478
479
480
481
482
483
484
485
486
487
488
489
490
491u8 acpi_ut_get_resource_header_length(void *aml)
492{
493 ACPI_FUNCTION_ENTRY();
494
495
496
497 if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
498 return (sizeof(struct aml_resource_large_header));
499 } else {
500 return (sizeof(struct aml_resource_small_header));
501 }
502}
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518u32 acpi_ut_get_descriptor_length(void *aml)
519{
520 ACPI_FUNCTION_ENTRY();
521
522
523
524
525
526 return (acpi_ut_get_resource_length(aml) +
527 acpi_ut_get_resource_header_length(aml));
528}
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544acpi_status
545acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag)
546{
547 acpi_status status;
548
549 ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
550
551
552
553 if (!obj_desc->buffer.length) {
554 *end_tag = obj_desc->buffer.pointer;
555 return_ACPI_STATUS(AE_OK);
556 }
557
558
559
560 status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer,
561 obj_desc->buffer.length, NULL,
562 (void **)end_tag);
563
564 return_ACPI_STATUS(status);
565}
566