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