dbtest.c revision 1.6 1 /*******************************************************************************
2 *
3 * Module Name: dbtest - Various debug-related tests
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acdebug.h"
47 #include "acnamesp.h"
48 #include "acpredef.h"
49
50
51 #define _COMPONENT ACPI_CA_DEBUGGER
52 ACPI_MODULE_NAME ("dbtest")
53
54
55 /* Local prototypes */
56
57 static void
58 AcpiDbTestAllObjects (
59 void);
60
61 static ACPI_STATUS
62 AcpiDbTestOneObject (
63 ACPI_HANDLE ObjHandle,
64 UINT32 NestingLevel,
65 void *Context,
66 void **ReturnValue);
67
68 static ACPI_STATUS
69 AcpiDbTestIntegerType (
70 ACPI_NAMESPACE_NODE *Node,
71 UINT32 BitLength);
72
73 static ACPI_STATUS
74 AcpiDbTestBufferType (
75 ACPI_NAMESPACE_NODE *Node,
76 UINT32 BitLength);
77
78 static ACPI_STATUS
79 AcpiDbTestStringType (
80 ACPI_NAMESPACE_NODE *Node,
81 UINT32 ByteLength);
82
83 static ACPI_STATUS
84 AcpiDbReadFromObject (
85 ACPI_NAMESPACE_NODE *Node,
86 ACPI_OBJECT_TYPE ExpectedType,
87 ACPI_OBJECT **Value);
88
89 static ACPI_STATUS
90 AcpiDbWriteToObject (
91 ACPI_NAMESPACE_NODE *Node,
92 ACPI_OBJECT *Value);
93
94 static void
95 AcpiDbEvaluateAllPredefinedNames (
96 char *CountArg);
97
98 static ACPI_STATUS
99 AcpiDbEvaluateOnePredefinedName (
100 ACPI_HANDLE ObjHandle,
101 UINT32 NestingLevel,
102 void *Context,
103 void **ReturnValue);
104
105 /*
106 * Test subcommands
107 */
108 static ACPI_DB_ARGUMENT_INFO AcpiDbTestTypes [] =
109 {
110 {"OBJECTS"},
111 {"PREDEFINED"},
112 {NULL} /* Must be null terminated */
113 };
114
115 #define CMD_TEST_OBJECTS 0
116 #define CMD_TEST_PREDEFINED 1
117
118 #define BUFFER_FILL_VALUE 0xFF
119
120 /*
121 * Support for the special debugger read/write control methods.
122 * These methods are installed into the current namespace and are
123 * used to read and write the various namespace objects. The point
124 * is to force the AML interpreter do all of the work.
125 */
126 #define ACPI_DB_READ_METHOD "\\_T98"
127 #define ACPI_DB_WRITE_METHOD "\\_T99"
128
129 static ACPI_HANDLE ReadHandle = NULL;
130 static ACPI_HANDLE WriteHandle = NULL;
131
132 /* ASL Definitions of the debugger read/write control methods */
133
134 #if 0
135 DefinitionBlock ("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
136 {
137 Method (_T98, 1, NotSerialized) /* Read */
138 {
139 Return (DeRefOf (Arg0))
140 }
141 }
142 DefinitionBlock ("ssdt2.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
143 {
144 Method (_T99, 2, NotSerialized) /* Write */
145 {
146 Store (Arg1, Arg0)
147 }
148 }
149 #endif
150
151 static unsigned char ReadMethodCode[] =
152 {
153 0x53,0x53,0x44,0x54,0x2E,0x00,0x00,0x00, /* 00000000 "SSDT...." */
154 0x02,0xC9,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */
155 0x44,0x45,0x42,0x55,0x47,0x00,0x00,0x00, /* 00000010 "DEBUG..." */
156 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
157 0x18,0x12,0x13,0x20,0x14,0x09,0x5F,0x54, /* 00000020 "... .._T" */
158 0x39,0x38,0x01,0xA4,0x83,0x68 /* 00000028 "98...h" */
159 };
160
161 static unsigned char WriteMethodCode[] =
162 {
163 0x53,0x53,0x44,0x54,0x2E,0x00,0x00,0x00, /* 00000000 "SSDT...." */
164 0x02,0x15,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */
165 0x44,0x45,0x42,0x55,0x47,0x00,0x00,0x00, /* 00000010 "DEBUG..." */
166 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
167 0x18,0x12,0x13,0x20,0x14,0x09,0x5F,0x54, /* 00000020 "... .._T" */
168 0x39,0x39,0x02,0x70,0x69,0x68 /* 00000028 "99.pih" */
169 };
170
171
172 /*******************************************************************************
173 *
174 * FUNCTION: AcpiDbExecuteTest
175 *
176 * PARAMETERS: TypeArg - Subcommand
177 *
178 * RETURN: None
179 *
180 * DESCRIPTION: Execute various debug tests.
181 *
182 * Note: Code is prepared for future expansion of the TEST command.
183 *
184 ******************************************************************************/
185
186 void
187 AcpiDbExecuteTest (
188 char *TypeArg)
189 {
190 UINT32 Temp;
191
192
193 AcpiUtStrupr (TypeArg);
194 Temp = AcpiDbMatchArgument (TypeArg, AcpiDbTestTypes);
195 if (Temp == ACPI_TYPE_NOT_FOUND)
196 {
197 AcpiOsPrintf ("Invalid or unsupported argument\n");
198 return;
199 }
200
201 switch (Temp)
202 {
203 case CMD_TEST_OBJECTS:
204
205 AcpiDbTestAllObjects ();
206 break;
207
208 case CMD_TEST_PREDEFINED:
209
210 AcpiDbEvaluateAllPredefinedNames (NULL);
211 break;
212
213 default:
214 break;
215 }
216 }
217
218
219 /*******************************************************************************
220 *
221 * FUNCTION: AcpiDbTestAllObjects
222 *
223 * PARAMETERS: None
224 *
225 * RETURN: None
226 *
227 * DESCRIPTION: This test implements the OBJECTS subcommand. It exercises the
228 * namespace by reading/writing/comparing all data objects such
229 * as integers, strings, buffers, fields, buffer fields, etc.
230 *
231 ******************************************************************************/
232
233 static void
234 AcpiDbTestAllObjects (
235 void)
236 {
237 ACPI_STATUS Status;
238
239
240 /* Install the debugger read-object control method if necessary */
241
242 if (!ReadHandle)
243 {
244 Status = AcpiInstallMethod (ReadMethodCode);
245 if (ACPI_FAILURE (Status))
246 {
247 AcpiOsPrintf ("%s, Could not install debugger read method\n",
248 AcpiFormatException (Status));
249 return;
250 }
251
252 Status = AcpiGetHandle (NULL, ACPI_DB_READ_METHOD, &ReadHandle);
253 if (ACPI_FAILURE (Status))
254 {
255 AcpiOsPrintf ("Could not obtain handle for debug method %s\n",
256 ACPI_DB_READ_METHOD);
257 return;
258 }
259 }
260
261 /* Install the debugger write-object control method if necessary */
262
263 if (!WriteHandle)
264 {
265 Status = AcpiInstallMethod (WriteMethodCode);
266 if (ACPI_FAILURE (Status))
267 {
268 AcpiOsPrintf ("%s, Could not install debugger write method\n",
269 AcpiFormatException (Status));
270 return;
271 }
272
273 Status = AcpiGetHandle (NULL, ACPI_DB_WRITE_METHOD, &WriteHandle);
274 if (ACPI_FAILURE (Status))
275 {
276 AcpiOsPrintf ("Could not obtain handle for debug method %s\n",
277 ACPI_DB_WRITE_METHOD);
278 return;
279 }
280 }
281
282 /* Walk the entire namespace, testing each supported named data object */
283
284 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
285 ACPI_UINT32_MAX, AcpiDbTestOneObject, NULL, NULL, NULL);
286 }
287
288
289 /*******************************************************************************
290 *
291 * FUNCTION: AcpiDbTestOneObject
292 *
293 * PARAMETERS: ACPI_WALK_CALLBACK
294 *
295 * RETURN: Status
296 *
297 * DESCRIPTION: Test one namespace object. Supported types are Integer,
298 * String, Buffer, BufferField, and FieldUnit. All other object
299 * types are simply ignored.
300 *
301 * Note: Support for Packages is not implemented.
302 *
303 ******************************************************************************/
304
305 static ACPI_STATUS
306 AcpiDbTestOneObject (
307 ACPI_HANDLE ObjHandle,
308 UINT32 NestingLevel,
309 void *Context,
310 void **ReturnValue)
311 {
312 ACPI_NAMESPACE_NODE *Node;
313 ACPI_OPERAND_OBJECT *ObjDesc;
314 ACPI_OPERAND_OBJECT *RegionObj;
315 ACPI_OBJECT_TYPE LocalType;
316 UINT32 BitLength = 0;
317 UINT32 ByteLength = 0;
318 ACPI_STATUS Status = AE_OK;
319
320
321 Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
322 ObjDesc = Node->Object;
323
324 /*
325 * For the supported types, get the actual bit length or
326 * byte length. Map the type to one of Integer/String/Buffer.
327 */
328 switch (Node->Type)
329 {
330 case ACPI_TYPE_INTEGER:
331
332 /* Integer width is either 32 or 64 */
333
334 LocalType = ACPI_TYPE_INTEGER;
335 BitLength = AcpiGbl_IntegerBitWidth;
336 break;
337
338 case ACPI_TYPE_STRING:
339
340 LocalType = ACPI_TYPE_STRING;
341 ByteLength = ObjDesc->String.Length;
342 break;
343
344 case ACPI_TYPE_BUFFER:
345
346 LocalType = ACPI_TYPE_BUFFER;
347 ByteLength = ObjDesc->Buffer.Length;
348 BitLength = ByteLength * 8;
349 break;
350
351 case ACPI_TYPE_FIELD_UNIT:
352 case ACPI_TYPE_BUFFER_FIELD:
353 case ACPI_TYPE_LOCAL_REGION_FIELD:
354 case ACPI_TYPE_LOCAL_INDEX_FIELD:
355 case ACPI_TYPE_LOCAL_BANK_FIELD:
356
357 LocalType = ACPI_TYPE_INTEGER;
358 if (ObjDesc)
359 {
360 /*
361 * Returned object will be a Buffer if the field length
362 * is larger than the size of an Integer (32 or 64 bits
363 * depending on the DSDT version).
364 */
365 BitLength = ObjDesc->CommonField.BitLength;
366 ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength);
367 if (BitLength > AcpiGbl_IntegerBitWidth)
368 {
369 LocalType = ACPI_TYPE_BUFFER;
370 }
371 }
372 break;
373
374 default:
375
376 /* Ignore all other types */
377
378 return (AE_OK);
379 }
380
381 /* Emit the common prefix: Type:Name */
382
383 AcpiOsPrintf ("%14s: %4.4s",
384 AcpiUtGetTypeName (Node->Type), Node->Name.Ascii);
385 if (!ObjDesc)
386 {
387 AcpiOsPrintf (" Ignoring, no attached object\n");
388 return (AE_OK);
389 }
390
391 /*
392 * Check for unsupported region types. Note: AcpiExec simulates
393 * access to SystemMemory, SystemIO, PCI_Config, and EC.
394 */
395 switch (Node->Type)
396 {
397 case ACPI_TYPE_LOCAL_REGION_FIELD:
398
399 RegionObj = ObjDesc->Field.RegionObj;
400 switch (RegionObj->Region.SpaceId)
401 {
402 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
403 case ACPI_ADR_SPACE_SYSTEM_IO:
404 case ACPI_ADR_SPACE_PCI_CONFIG:
405 case ACPI_ADR_SPACE_EC:
406
407 break;
408
409 default:
410
411 AcpiOsPrintf (" %s space is not supported [%4.4s]\n",
412 AcpiUtGetRegionName (RegionObj->Region.SpaceId),
413 RegionObj->Region.Node->Name.Ascii);
414 return (AE_OK);
415 }
416 break;
417
418 default:
419 break;
420 }
421
422 /* At this point, we have resolved the object to one of the major types */
423
424 switch (LocalType)
425 {
426 case ACPI_TYPE_INTEGER:
427
428 Status = AcpiDbTestIntegerType (Node, BitLength);
429 break;
430
431 case ACPI_TYPE_STRING:
432
433 Status = AcpiDbTestStringType (Node, ByteLength);
434 break;
435
436 case ACPI_TYPE_BUFFER:
437
438 Status = AcpiDbTestBufferType (Node, BitLength);
439 break;
440
441 default:
442
443 AcpiOsPrintf (" Ignoring, type not implemented (%2.2X)",
444 LocalType);
445 break;
446 }
447
448 switch (Node->Type)
449 {
450 case ACPI_TYPE_LOCAL_REGION_FIELD:
451
452 RegionObj = ObjDesc->Field.RegionObj;
453 AcpiOsPrintf (" (%s)",
454 AcpiUtGetRegionName (RegionObj->Region.SpaceId));
455 break;
456
457 default:
458 break;
459 }
460
461 AcpiOsPrintf ("\n");
462 return (Status);
463 }
464
465
466 /*******************************************************************************
467 *
468 * FUNCTION: AcpiDbTestIntegerType
469 *
470 * PARAMETERS: Node - Parent NS node for the object
471 * BitLength - Actual length of the object. Used for
472 * support of arbitrary length FieldUnit
473 * and BufferField objects.
474 *
475 * RETURN: Status
476 *
477 * DESCRIPTION: Test read/write for an Integer-valued object. Performs a
478 * write/read/compare of an arbitrary new value, then performs
479 * a write/read/compare of the original value.
480 *
481 ******************************************************************************/
482
483 static ACPI_STATUS
484 AcpiDbTestIntegerType (
485 ACPI_NAMESPACE_NODE *Node,
486 UINT32 BitLength)
487 {
488 ACPI_OBJECT *Temp1 = NULL;
489 ACPI_OBJECT *Temp2 = NULL;
490 ACPI_OBJECT *Temp3 = NULL;
491 ACPI_OBJECT WriteValue;
492 UINT64 ValueToWrite;
493 ACPI_STATUS Status;
494
495
496 if (BitLength > 64)
497 {
498 AcpiOsPrintf (" Invalid length for an Integer: %u", BitLength);
499 return (AE_OK);
500 }
501
502 /* Read the original value */
503
504 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp1);
505 if (ACPI_FAILURE (Status))
506 {
507 return (Status);
508 }
509
510 AcpiOsPrintf (" (%4.4X/%3.3X) %8.8X%8.8X",
511 BitLength, ACPI_ROUND_BITS_UP_TO_BYTES (BitLength),
512 ACPI_FORMAT_UINT64 (Temp1->Integer.Value));
513
514 ValueToWrite = ACPI_UINT64_MAX >> (64 - BitLength);
515 if (Temp1->Integer.Value == ValueToWrite)
516 {
517 ValueToWrite = 0;
518 }
519
520 /* Write a new value */
521
522 WriteValue.Type = ACPI_TYPE_INTEGER;
523 WriteValue.Integer.Value = ValueToWrite;
524 Status = AcpiDbWriteToObject (Node, &WriteValue);
525 if (ACPI_FAILURE (Status))
526 {
527 goto Exit;
528 }
529
530 /* Ensure that we can read back the new value */
531
532 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp2);
533 if (ACPI_FAILURE (Status))
534 {
535 goto Exit;
536 }
537
538 if (Temp2->Integer.Value != ValueToWrite)
539 {
540 AcpiOsPrintf (" MISMATCH 2: %8.8X%8.8X, expecting %8.8X%8.8X",
541 ACPI_FORMAT_UINT64 (Temp2->Integer.Value),
542 ACPI_FORMAT_UINT64 (ValueToWrite));
543 }
544
545 /* Write back the original value */
546
547 WriteValue.Integer.Value = Temp1->Integer.Value;
548 Status = AcpiDbWriteToObject (Node, &WriteValue);
549 if (ACPI_FAILURE (Status))
550 {
551 goto Exit;
552 }
553
554 /* Ensure that we can read back the original value */
555
556 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp3);
557 if (ACPI_FAILURE (Status))
558 {
559 goto Exit;
560 }
561
562 if (Temp3->Integer.Value != Temp1->Integer.Value)
563 {
564 AcpiOsPrintf (" MISMATCH 3: %8.8X%8.8X, expecting %8.8X%8.8X",
565 ACPI_FORMAT_UINT64 (Temp3->Integer.Value),
566 ACPI_FORMAT_UINT64 (Temp1->Integer.Value));
567 }
568
569 Exit:
570 if (Temp1) {AcpiOsFree (Temp1);}
571 if (Temp2) {AcpiOsFree (Temp2);}
572 if (Temp3) {AcpiOsFree (Temp3);}
573 return (AE_OK);
574 }
575
576
577 /*******************************************************************************
578 *
579 * FUNCTION: AcpiDbTestBufferType
580 *
581 * PARAMETERS: Node - Parent NS node for the object
582 * BitLength - Actual length of the object.
583 *
584 * RETURN: Status
585 *
586 * DESCRIPTION: Test read/write for an Buffer-valued object. Performs a
587 * write/read/compare of an arbitrary new value, then performs
588 * a write/read/compare of the original value.
589 *
590 ******************************************************************************/
591
592 static ACPI_STATUS
593 AcpiDbTestBufferType (
594 ACPI_NAMESPACE_NODE *Node,
595 UINT32 BitLength)
596 {
597 ACPI_OBJECT *Temp1 = NULL;
598 ACPI_OBJECT *Temp2 = NULL;
599 ACPI_OBJECT *Temp3 = NULL;
600 UINT8 *Buffer;
601 ACPI_OBJECT WriteValue;
602 ACPI_STATUS Status;
603 UINT32 ByteLength;
604 UINT32 i;
605 UINT8 ExtraBits;
606
607
608 ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength);
609 if (ByteLength == 0)
610 {
611 AcpiOsPrintf (" Ignoring zero length buffer");
612 return (AE_OK);
613 }
614
615 /* Allocate a local buffer */
616
617 Buffer = ACPI_ALLOCATE_ZEROED (ByteLength);
618 if (!Buffer)
619 {
620 return (AE_NO_MEMORY);
621 }
622
623 /* Read the original value */
624
625 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp1);
626 if (ACPI_FAILURE (Status))
627 {
628 goto Exit;
629 }
630
631 /* Emit a few bytes of the buffer */
632
633 AcpiOsPrintf (" (%4.4X/%3.3X)", BitLength, Temp1->Buffer.Length);
634 for (i = 0; ((i < 4) && (i < ByteLength)); i++)
635 {
636 AcpiOsPrintf (" %2.2X", Temp1->Buffer.Pointer[i]);
637 }
638 AcpiOsPrintf ("... ");
639
640 /*
641 * Write a new value.
642 *
643 * Handle possible extra bits at the end of the buffer. Can
644 * happen for FieldUnits larger than an integer, but the bit
645 * count is not an integral number of bytes. Zero out the
646 * unused bits.
647 */
648 memset (Buffer, BUFFER_FILL_VALUE, ByteLength);
649 ExtraBits = BitLength % 8;
650 if (ExtraBits)
651 {
652 Buffer [ByteLength - 1] = ACPI_MASK_BITS_ABOVE (ExtraBits);
653 }
654
655 WriteValue.Type = ACPI_TYPE_BUFFER;
656 WriteValue.Buffer.Length = ByteLength;
657 WriteValue.Buffer.Pointer = Buffer;
658
659 Status = AcpiDbWriteToObject (Node, &WriteValue);
660 if (ACPI_FAILURE (Status))
661 {
662 goto Exit;
663 }
664
665 /* Ensure that we can read back the new value */
666
667 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp2);
668 if (ACPI_FAILURE (Status))
669 {
670 goto Exit;
671 }
672
673 if (memcmp (Temp2->Buffer.Pointer, Buffer, ByteLength))
674 {
675 AcpiOsPrintf (" MISMATCH 2: New buffer value");
676 }
677
678 /* Write back the original value */
679
680 WriteValue.Buffer.Length = ByteLength;
681 WriteValue.Buffer.Pointer = Temp1->Buffer.Pointer;
682
683 Status = AcpiDbWriteToObject (Node, &WriteValue);
684 if (ACPI_FAILURE (Status))
685 {
686 goto Exit;
687 }
688
689 /* Ensure that we can read back the original value */
690
691 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp3);
692 if (ACPI_FAILURE (Status))
693 {
694 goto Exit;
695 }
696
697 if (memcmp (Temp1->Buffer.Pointer,
698 Temp3->Buffer.Pointer, ByteLength))
699 {
700 AcpiOsPrintf (" MISMATCH 3: While restoring original buffer");
701 }
702
703 Exit:
704 ACPI_FREE (Buffer);
705 if (Temp1) {AcpiOsFree (Temp1);}
706 if (Temp2) {AcpiOsFree (Temp2);}
707 if (Temp3) {AcpiOsFree (Temp3);}
708 return (Status);
709 }
710
711
712 /*******************************************************************************
713 *
714 * FUNCTION: AcpiDbTestStringType
715 *
716 * PARAMETERS: Node - Parent NS node for the object
717 * ByteLength - Actual length of the object.
718 *
719 * RETURN: Status
720 *
721 * DESCRIPTION: Test read/write for an String-valued object. Performs a
722 * write/read/compare of an arbitrary new value, then performs
723 * a write/read/compare of the original value.
724 *
725 ******************************************************************************/
726
727 static ACPI_STATUS
728 AcpiDbTestStringType (
729 ACPI_NAMESPACE_NODE *Node,
730 UINT32 ByteLength)
731 {
732 ACPI_OBJECT *Temp1 = NULL;
733 ACPI_OBJECT *Temp2 = NULL;
734 ACPI_OBJECT *Temp3 = NULL;
735 char *ValueToWrite = __UNCONST("Test String from AML Debugger");
736 ACPI_OBJECT WriteValue;
737 ACPI_STATUS Status;
738
739
740 /* Read the original value */
741
742 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp1);
743 if (ACPI_FAILURE (Status))
744 {
745 return (Status);
746 }
747
748 AcpiOsPrintf (" (%4.4X/%3.3X) \"%s\"", (Temp1->String.Length * 8),
749 Temp1->String.Length, Temp1->String.Pointer);
750
751 /* Write a new value */
752
753 WriteValue.Type = ACPI_TYPE_STRING;
754 WriteValue.String.Length = strlen (ValueToWrite);
755 WriteValue.String.Pointer = ValueToWrite;
756
757 Status = AcpiDbWriteToObject (Node, &WriteValue);
758 if (ACPI_FAILURE (Status))
759 {
760 goto Exit;
761 }
762
763 /* Ensure that we can read back the new value */
764
765 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp2);
766 if (ACPI_FAILURE (Status))
767 {
768 goto Exit;
769 }
770
771 if (strcmp (Temp2->String.Pointer, ValueToWrite))
772 {
773 AcpiOsPrintf (" MISMATCH 2: %s, expecting %s",
774 Temp2->String.Pointer, ValueToWrite);
775 }
776
777 /* Write back the original value */
778
779 WriteValue.String.Length = strlen (Temp1->String.Pointer);
780 WriteValue.String.Pointer = Temp1->String.Pointer;
781
782 Status = AcpiDbWriteToObject (Node, &WriteValue);
783 if (ACPI_FAILURE (Status))
784 {
785 goto Exit;
786 }
787
788 /* Ensure that we can read back the original value */
789
790 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp3);
791 if (ACPI_FAILURE (Status))
792 {
793 goto Exit;
794 }
795
796 if (strcmp (Temp1->String.Pointer, Temp3->String.Pointer))
797 {
798 AcpiOsPrintf (" MISMATCH 3: %s, expecting %s",
799 Temp3->String.Pointer, Temp1->String.Pointer);
800 }
801
802 Exit:
803 if (Temp1) {AcpiOsFree (Temp1);}
804 if (Temp2) {AcpiOsFree (Temp2);}
805 if (Temp3) {AcpiOsFree (Temp3);}
806 return (Status);
807 }
808
809
810 /*******************************************************************************
811 *
812 * FUNCTION: AcpiDbReadFromObject
813 *
814 * PARAMETERS: Node - Parent NS node for the object
815 * ExpectedType - Object type expected from the read
816 * Value - Where the value read is returned
817 *
818 * RETURN: Status
819 *
820 * DESCRIPTION: Performs a read from the specified object by invoking the
821 * special debugger control method that reads the object. Thus,
822 * the AML interpreter is doing all of the work, increasing the
823 * validity of the test.
824 *
825 ******************************************************************************/
826
827 static ACPI_STATUS
828 AcpiDbReadFromObject (
829 ACPI_NAMESPACE_NODE *Node,
830 ACPI_OBJECT_TYPE ExpectedType,
831 ACPI_OBJECT **Value)
832 {
833 ACPI_OBJECT *RetValue;
834 ACPI_OBJECT_LIST ParamObjects;
835 ACPI_OBJECT Params[2];
836 ACPI_BUFFER ReturnObj;
837 ACPI_STATUS Status;
838
839
840 Params[0].Type = ACPI_TYPE_LOCAL_REFERENCE;
841 Params[0].Reference.ActualType = Node->Type;
842 Params[0].Reference.Handle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
843
844 ParamObjects.Count = 1;
845 ParamObjects.Pointer = Params;
846
847 ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
848
849 AcpiGbl_MethodExecuting = TRUE;
850 Status = AcpiEvaluateObject (ReadHandle, NULL,
851 &ParamObjects, &ReturnObj);
852 AcpiGbl_MethodExecuting = FALSE;
853
854 if (ACPI_FAILURE (Status))
855 {
856 AcpiOsPrintf ("Could not read from object, %s",
857 AcpiFormatException (Status));
858 return (Status);
859 }
860
861 RetValue = (ACPI_OBJECT *) ReturnObj.Pointer;
862
863 switch (RetValue->Type)
864 {
865 case ACPI_TYPE_INTEGER:
866 case ACPI_TYPE_BUFFER:
867 case ACPI_TYPE_STRING:
868 /*
869 * Did we receive the type we wanted? Most important for the
870 * Integer/Buffer case (when a field is larger than an Integer,
871 * it should return a Buffer).
872 */
873 if (RetValue->Type != ExpectedType)
874 {
875 AcpiOsPrintf (" Type mismatch: Expected %s, Received %s",
876 AcpiUtGetTypeName (ExpectedType),
877 AcpiUtGetTypeName (RetValue->Type));
878
879 return (AE_TYPE);
880 }
881
882 *Value = RetValue;
883 break;
884
885 default:
886
887 AcpiOsPrintf (" Unsupported return object type, %s",
888 AcpiUtGetTypeName (RetValue->Type));
889
890 AcpiOsFree (ReturnObj.Pointer);
891 return (AE_TYPE);
892 }
893
894 return (Status);
895 }
896
897
898 /*******************************************************************************
899 *
900 * FUNCTION: AcpiDbWriteToObject
901 *
902 * PARAMETERS: Node - Parent NS node for the object
903 * Value - Value to be written
904 *
905 * RETURN: Status
906 *
907 * DESCRIPTION: Performs a write to the specified object by invoking the
908 * special debugger control method that writes the object. Thus,
909 * the AML interpreter is doing all of the work, increasing the
910 * validity of the test.
911 *
912 ******************************************************************************/
913
914 static ACPI_STATUS
915 AcpiDbWriteToObject (
916 ACPI_NAMESPACE_NODE *Node,
917 ACPI_OBJECT *Value)
918 {
919 ACPI_OBJECT_LIST ParamObjects;
920 ACPI_OBJECT Params[2];
921 ACPI_STATUS Status;
922
923
924 Params[0].Type = ACPI_TYPE_LOCAL_REFERENCE;
925 Params[0].Reference.ActualType = Node->Type;
926 Params[0].Reference.Handle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
927
928 /* Copy the incoming user parameter */
929
930 memcpy (&Params[1], Value, sizeof (ACPI_OBJECT));
931
932 ParamObjects.Count = 2;
933 ParamObjects.Pointer = Params;
934
935 AcpiGbl_MethodExecuting = TRUE;
936 Status = AcpiEvaluateObject (WriteHandle, NULL, &ParamObjects, NULL);
937 AcpiGbl_MethodExecuting = FALSE;
938
939 if (ACPI_FAILURE (Status))
940 {
941 AcpiOsPrintf ("Could not write to object, %s",
942 AcpiFormatException (Status));
943 }
944
945 return (Status);
946 }
947
948
949 /*******************************************************************************
950 *
951 * FUNCTION: AcpiDbEvaluateAllPredefinedNames
952 *
953 * PARAMETERS: CountArg - Max number of methods to execute
954 *
955 * RETURN: None
956 *
957 * DESCRIPTION: Namespace batch execution. Execute predefined names in the
958 * namespace, up to the max count, if specified.
959 *
960 ******************************************************************************/
961
962 static void
963 AcpiDbEvaluateAllPredefinedNames (
964 char *CountArg)
965 {
966 ACPI_DB_EXECUTE_WALK Info;
967
968
969 Info.Count = 0;
970 Info.MaxCount = ACPI_UINT32_MAX;
971
972 if (CountArg)
973 {
974 Info.MaxCount = strtoul (CountArg, NULL, 0);
975 }
976
977 /* Search all nodes in namespace */
978
979 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
980 ACPI_UINT32_MAX, AcpiDbEvaluateOnePredefinedName, NULL,
981 (void *) &Info, NULL);
982
983 AcpiOsPrintf (
984 "Evaluated %u predefined names in the namespace\n", Info.Count);
985 }
986
987
988 /*******************************************************************************
989 *
990 * FUNCTION: AcpiDbEvaluateOnePredefinedName
991 *
992 * PARAMETERS: Callback from WalkNamespace
993 *
994 * RETURN: Status
995 *
996 * DESCRIPTION: Batch execution module. Currently only executes predefined
997 * ACPI names.
998 *
999 ******************************************************************************/
1000
1001 static ACPI_STATUS
1002 AcpiDbEvaluateOnePredefinedName (
1003 ACPI_HANDLE ObjHandle,
1004 UINT32 NestingLevel,
1005 void *Context,
1006 void **ReturnValue)
1007 {
1008 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
1009 ACPI_DB_EXECUTE_WALK *Info = (ACPI_DB_EXECUTE_WALK *) Context;
1010 char *Pathname;
1011 const ACPI_PREDEFINED_INFO *Predefined;
1012 ACPI_DEVICE_INFO *ObjInfo;
1013 ACPI_OBJECT_LIST ParamObjects;
1014 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS];
1015 ACPI_OBJECT *ThisParam;
1016 ACPI_BUFFER ReturnObj;
1017 ACPI_STATUS Status;
1018 UINT16 ArgTypeList;
1019 UINT8 ArgCount;
1020 UINT8 ArgType;
1021 UINT32 i;
1022
1023
1024 /* The name must be a predefined ACPI name */
1025
1026 Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii);
1027 if (!Predefined)
1028 {
1029 return (AE_OK);
1030 }
1031
1032 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)
1033 {
1034 return (AE_OK);
1035 }
1036
1037 Pathname = AcpiNsGetNormalizedPathname (Node, TRUE);
1038 if (!Pathname)
1039 {
1040 return (AE_OK);
1041 }
1042
1043 /* Get the object info for number of method parameters */
1044
1045 Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo);
1046 if (ACPI_FAILURE (Status))
1047 {
1048 ACPI_FREE (Pathname);
1049 return (Status);
1050 }
1051
1052 ParamObjects.Count = 0;
1053 ParamObjects.Pointer = NULL;
1054
1055 if (ObjInfo->Type == ACPI_TYPE_METHOD)
1056 {
1057 /* Setup default parameters (with proper types) */
1058
1059 ArgTypeList = Predefined->Info.ArgumentList;
1060 ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList);
1061
1062 /*
1063 * Setup the ACPI-required number of arguments, regardless of what
1064 * the actual method defines. If there is a difference, then the
1065 * method is wrong and a warning will be issued during execution.
1066 */
1067 ThisParam = Params;
1068 for (i = 0; i < ArgCount; i++)
1069 {
1070 ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList);
1071 ThisParam->Type = ArgType;
1072
1073 switch (ArgType)
1074 {
1075 case ACPI_TYPE_INTEGER:
1076
1077 ThisParam->Integer.Value = 1;
1078 break;
1079
1080 case ACPI_TYPE_STRING:
1081
1082 ThisParam->String.Pointer =
1083 __UNCONST("This is the default argument string");
1084 ThisParam->String.Length =
1085 strlen (ThisParam->String.Pointer);
1086 break;
1087
1088 case ACPI_TYPE_BUFFER:
1089
1090 ThisParam->Buffer.Pointer = (UINT8 *) Params; /* just a garbage buffer */
1091 ThisParam->Buffer.Length = 48;
1092 break;
1093
1094 case ACPI_TYPE_PACKAGE:
1095
1096 ThisParam->Package.Elements = NULL;
1097 ThisParam->Package.Count = 0;
1098 break;
1099
1100 default:
1101
1102 AcpiOsPrintf ("%s: Unsupported argument type: %u\n",
1103 Pathname, ArgType);
1104 break;
1105 }
1106
1107 ThisParam++;
1108 }
1109
1110 ParamObjects.Count = ArgCount;
1111 ParamObjects.Pointer = Params;
1112 }
1113
1114 ACPI_FREE (ObjInfo);
1115 ReturnObj.Pointer = NULL;
1116 ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
1117
1118 /* Do the actual method execution */
1119
1120 AcpiGbl_MethodExecuting = TRUE;
1121
1122 Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj);
1123
1124 AcpiOsPrintf ("%-32s returned %s\n",
1125 Pathname, AcpiFormatException (Status));
1126 AcpiGbl_MethodExecuting = FALSE;
1127 ACPI_FREE (Pathname);
1128
1129 /* Ignore status from method execution */
1130
1131 Status = AE_OK;
1132
1133 /* Update count, check if we have executed enough methods */
1134
1135 Info->Count++;
1136 if (Info->Count >= Info->MaxCount)
1137 {
1138 Status = AE_CTRL_TERMINATE;
1139 }
1140
1141 return (Status);
1142 }
1143