Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
48524 views
1
/*******************************************************************************
2
*
3
* Module Name: dmbuffer - AML disassembler, buffer and string support
4
*
5
******************************************************************************/
6
7
/******************************************************************************
8
*
9
* 1. Copyright Notice
10
*
11
* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
12
* All rights reserved.
13
*
14
* 2. License
15
*
16
* 2.1. This is your license from Intel Corp. under its intellectual property
17
* rights. You may have additional license terms from the party that provided
18
* you this software, covering your right to use that party's intellectual
19
* property rights.
20
*
21
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
* copy of the source code appearing in this file ("Covered Code") an
23
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
* base code distributed originally by Intel ("Original Intel Code") to copy,
25
* make derivatives, distribute, use and display any portion of the Covered
26
* Code in any form, with the right to sublicense such rights; and
27
*
28
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
* license (with the right to sublicense), under only those claims of Intel
30
* patents that are infringed by the Original Intel Code, to make, use, sell,
31
* offer to sell, and import the Covered Code and derivative works thereof
32
* solely to the minimum extent necessary to exercise the above copyright
33
* license, and in no event shall the patent license extend to any additions
34
* to or modifications of the Original Intel Code. No other license or right
35
* is granted directly or by implication, estoppel or otherwise;
36
*
37
* The above copyright and patent license is granted only if the following
38
* conditions are met:
39
*
40
* 3. Conditions
41
*
42
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
* Redistribution of source code of any substantial portion of the Covered
44
* Code or modification with rights to further distribute source must include
45
* the above Copyright Notice, the above License, this list of Conditions,
46
* and the following Disclaimer and Export Compliance provision. In addition,
47
* Licensee must cause all Covered Code to which Licensee contributes to
48
* contain a file documenting the changes Licensee made to create that Covered
49
* Code and the date of any change. Licensee must include in that file the
50
* documentation of any changes made by any predecessor Licensee. Licensee
51
* must include a prominent statement that the modification is derived,
52
* directly or indirectly, from Original Intel Code.
53
*
54
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
* Redistribution of source code of any substantial portion of the Covered
56
* Code or modification without rights to further distribute source must
57
* include the following Disclaimer and Export Compliance provision in the
58
* documentation and/or other materials provided with distribution. In
59
* addition, Licensee may not authorize further sublicense of source of any
60
* portion of the Covered Code, and must include terms to the effect that the
61
* license from Licensee to its licensee is limited to the intellectual
62
* property embodied in the software Licensee provides to its licensee, and
63
* not to intellectual property embodied in modifications its licensee may
64
* make.
65
*
66
* 3.3. Redistribution of Executable. Redistribution in executable form of any
67
* substantial portion of the Covered Code or modification must reproduce the
68
* above Copyright Notice, and the following Disclaimer and Export Compliance
69
* provision in the documentation and/or other materials provided with the
70
* distribution.
71
*
72
* 3.4. Intel retains all right, title, and interest in and to the Original
73
* Intel Code.
74
*
75
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
* Intel shall be used in advertising or otherwise to promote the sale, use or
77
* other dealings in products derived from or relating to the Covered Code
78
* without prior written authorization from Intel.
79
*
80
* 4. Disclaimer and Export Compliance
81
*
82
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
* PARTICULAR PURPOSE.
89
*
90
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
* LIMITED REMEDY.
98
*
99
* 4.3. Licensee shall not export, either directly or indirectly, any of this
100
* software or system incorporating such software without first obtaining any
101
* required license or other approval from the U. S. Department of Commerce or
102
* any other agency or department of the United States Government. In the
103
* event Licensee exports any such software from the United States or
104
* re-exports any such software from a foreign destination, Licensee shall
105
* ensure that the distribution and export/re-export of the software is in
106
* compliance with all laws, regulations, orders, or other restrictions of the
107
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
* any of its subsidiaries will export/re-export any technical data, process,
109
* software, or service, directly or indirectly, to any country for which the
110
* United States government or any agency thereof requires an export license,
111
* other governmental approval, or letter of assurance, without first obtaining
112
* such license, approval or letter.
113
*
114
*****************************************************************************
115
*
116
* Alternatively, you may choose to be licensed under the terms of the
117
* following license:
118
*
119
* Redistribution and use in source and binary forms, with or without
120
* modification, are permitted provided that the following conditions
121
* are met:
122
* 1. Redistributions of source code must retain the above copyright
123
* notice, this list of conditions, and the following disclaimer,
124
* without modification.
125
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
126
* substantially similar to the "NO WARRANTY" disclaimer below
127
* ("Disclaimer") and any redistribution must be conditioned upon
128
* including a substantially similar Disclaimer requirement for further
129
* binary redistribution.
130
* 3. Neither the names of the above-listed copyright holders nor the names
131
* of any contributors may be used to endorse or promote products derived
132
* from this software without specific prior written permission.
133
*
134
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
*
146
* Alternatively, you may choose to be licensed under the terms of the
147
* GNU General Public License ("GPL") version 2 as published by the Free
148
* Software Foundation.
149
*
150
*****************************************************************************/
151
152
#include <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/acutils.h>
155
#include <contrib/dev/acpica/include/acdisasm.h>
156
#include <contrib/dev/acpica/include/acparser.h>
157
#include <contrib/dev/acpica/include/amlcode.h>
158
#include <contrib/dev/acpica/include/acinterp.h>
159
160
161
#define _COMPONENT ACPI_CA_DEBUGGER
162
ACPI_MODULE_NAME ("dmbuffer")
163
164
/* Local prototypes */
165
166
static void
167
AcpiDmUuid (
168
ACPI_PARSE_OBJECT *Op);
169
170
static void
171
AcpiDmUnicode (
172
ACPI_PARSE_OBJECT *Op);
173
174
static void
175
AcpiDmGetHardwareIdType (
176
ACPI_PARSE_OBJECT *Op);
177
178
static void
179
AcpiDmPldBuffer (
180
UINT32 Level,
181
UINT8 *ByteData,
182
UINT32 ByteCount);
183
184
static const char *
185
AcpiDmFindNameByIndex (
186
UINT64 Index,
187
const char **List);
188
189
190
#define ACPI_BUFFER_BYTES_PER_LINE 8
191
192
193
/*******************************************************************************
194
*
195
* FUNCTION: AcpiDmDisasmByteList
196
*
197
* PARAMETERS: Level - Current source code indentation level
198
* ByteData - Pointer to the byte list
199
* ByteCount - Length of the byte list
200
*
201
* RETURN: None
202
*
203
* DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed
204
* with the hex buffer offset.
205
*
206
******************************************************************************/
207
208
void
209
AcpiDmDisasmByteList (
210
UINT32 Level,
211
UINT8 *ByteData,
212
UINT32 ByteCount)
213
{
214
UINT32 i;
215
UINT32 j;
216
UINT32 CurrentIndex;
217
UINT8 BufChar;
218
219
220
if (!ByteCount)
221
{
222
return;
223
}
224
225
for (i = 0; i < ByteCount; i += ACPI_BUFFER_BYTES_PER_LINE)
226
{
227
/* Line indent and offset prefix for each new line */
228
229
AcpiDmIndent (Level);
230
if (ByteCount > ACPI_BUFFER_BYTES_PER_LINE)
231
{
232
AcpiOsPrintf ("/* %04X */ ", i);
233
}
234
235
/* Dump the actual hex values */
236
237
for (j = 0; j < ACPI_BUFFER_BYTES_PER_LINE; j++)
238
{
239
CurrentIndex = i + j;
240
if (CurrentIndex >= ByteCount)
241
{
242
/* Dump fill spaces */
243
244
AcpiOsPrintf (" ");
245
continue;
246
}
247
248
AcpiOsPrintf (" 0x%2.2X", ByteData[CurrentIndex]);
249
250
/* Add comma if there are more bytes to display */
251
252
if (CurrentIndex < (ByteCount - 1))
253
{
254
AcpiOsPrintf (",");
255
}
256
else
257
{
258
AcpiOsPrintf (" ");
259
}
260
}
261
262
/* Dump the ASCII equivalents within a comment */
263
264
AcpiOsPrintf (" // ");
265
for (j = 0; j < ACPI_BUFFER_BYTES_PER_LINE; j++)
266
{
267
CurrentIndex = i + j;
268
if (CurrentIndex >= ByteCount)
269
{
270
break;
271
}
272
273
BufChar = ByteData[CurrentIndex];
274
if (isprint (BufChar))
275
{
276
AcpiOsPrintf ("%c", BufChar);
277
}
278
else
279
{
280
AcpiOsPrintf (".");
281
}
282
}
283
284
/* Finished with this line */
285
286
AcpiOsPrintf ("\n");
287
}
288
}
289
290
291
/*******************************************************************************
292
*
293
* FUNCTION: AcpiDmByteList
294
*
295
* PARAMETERS: Info - Parse tree walk info
296
* Op - Byte list op
297
*
298
* RETURN: None
299
*
300
* DESCRIPTION: Dump a buffer byte list, handling the various types of buffers.
301
* Buffer type must be already set in the Op DisasmOpcode.
302
*
303
******************************************************************************/
304
305
void
306
AcpiDmByteList (
307
ACPI_OP_WALK_INFO *Info,
308
ACPI_PARSE_OBJECT *Op)
309
{
310
UINT8 *ByteData;
311
UINT32 ByteCount;
312
313
314
ByteData = Op->Named.Data;
315
ByteCount = (UINT32) Op->Common.Value.Integer;
316
317
/*
318
* The byte list belongs to a buffer, and can be produced by either
319
* a ResourceTemplate, Unicode, quoted string, or a plain byte list.
320
*/
321
switch (Op->Common.Parent->Common.DisasmOpcode)
322
{
323
case ACPI_DASM_RESOURCE:
324
325
AcpiDmResourceTemplate (
326
Info, Op->Common.Parent, ByteData, ByteCount);
327
break;
328
329
case ACPI_DASM_STRING:
330
331
AcpiDmIndent (Info->Level);
332
AcpiUtPrintString ((char *) ByteData, ACPI_UINT16_MAX);
333
AcpiOsPrintf ("\n");
334
break;
335
336
case ACPI_DASM_UUID:
337
338
AcpiDmUuid (Op);
339
break;
340
341
case ACPI_DASM_UNICODE:
342
343
AcpiDmUnicode (Op);
344
break;
345
346
case ACPI_DASM_PLD_METHOD:
347
#if 0
348
AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount);
349
#endif
350
AcpiDmPldBuffer (Info->Level, ByteData, ByteCount);
351
break;
352
353
case ACPI_DASM_BUFFER:
354
default:
355
/*
356
* Not a resource, string, or unicode string.
357
* Just dump the buffer
358
*/
359
AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount);
360
break;
361
}
362
}
363
364
365
/*******************************************************************************
366
*
367
* FUNCTION: AcpiDmIsUuidBuffer
368
*
369
* PARAMETERS: Op - Buffer Object to be examined
370
*
371
* RETURN: TRUE if buffer contains a UUID
372
*
373
* DESCRIPTION: Determine if a buffer Op contains a UUID
374
*
375
* To help determine whether the buffer is a UUID versus a raw data buffer,
376
* there a are a couple bytes we can look at:
377
*
378
* xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
379
*
380
* The variant covered by the UUID specification is indicated by the two most
381
* significant bits of N being 1 0 (i.e., the hexadecimal N will always be
382
* 8, 9, A, or B).
383
*
384
* The variant covered by the UUID specification has five versions. For this
385
* variant, the four bits of M indicates the UUID version (i.e., the
386
* hexadecimal M will be either 1, 2, 3, 4, or 5).
387
*
388
******************************************************************************/
389
390
BOOLEAN
391
AcpiDmIsUuidBuffer (
392
ACPI_PARSE_OBJECT *Op)
393
{
394
UINT8 *ByteData;
395
UINT32 ByteCount;
396
ACPI_PARSE_OBJECT *SizeOp;
397
ACPI_PARSE_OBJECT *NextOp;
398
399
400
/* Buffer size is the buffer argument */
401
402
SizeOp = Op->Common.Value.Arg;
403
if (!SizeOp)
404
{
405
return (FALSE);
406
}
407
408
/* Next, the initializer byte list to examine */
409
410
NextOp = SizeOp->Common.Next;
411
if (!NextOp)
412
{
413
return (FALSE);
414
}
415
416
/* Extract the byte list info */
417
418
ByteData = NextOp->Named.Data;
419
ByteCount = (UINT32) NextOp->Common.Value.Integer;
420
421
/* Byte count must be exactly 16 */
422
423
if (ByteCount != UUID_BUFFER_LENGTH)
424
{
425
return (FALSE);
426
}
427
428
/* Check for valid "M" and "N" values (see function header above) */
429
430
if (((ByteData[7] & 0xF0) == 0x00) || /* M={1,2,3,4,5} */
431
((ByteData[7] & 0xF0) > 0x50) ||
432
((ByteData[8] & 0xF0) < 0x80) || /* N={8,9,A,B} */
433
((ByteData[8] & 0xF0) > 0xB0))
434
{
435
return (FALSE);
436
}
437
438
/* Ignore the Size argument in the disassembly of this buffer op */
439
440
SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
441
return (TRUE);
442
}
443
444
445
/*******************************************************************************
446
*
447
* FUNCTION: AcpiDmUuid
448
*
449
* PARAMETERS: Op - Byte List op containing a UUID
450
*
451
* RETURN: None
452
*
453
* DESCRIPTION: Dump a buffer containing a UUID as a standard ASCII string.
454
*
455
* Output Format:
456
* In its canonical form, the UUID is represented by a string containing 32
457
* lowercase hexadecimal digits, displayed in 5 groups separated by hyphens.
458
* The complete form is 8-4-4-4-12 for a total of 36 characters (32
459
* alphanumeric characters representing hex digits and 4 hyphens). In bytes,
460
* 4-2-2-2-6. Example:
461
*
462
* ToUUID ("107ededd-d381-4fd7-8da9-08e9a6c79644")
463
*
464
******************************************************************************/
465
466
static void
467
AcpiDmUuid (
468
ACPI_PARSE_OBJECT *Op)
469
{
470
UINT8 *Data;
471
const char *Description;
472
473
474
Data = ACPI_CAST_PTR (UINT8, Op->Named.Data);
475
476
/* Emit the 36-byte UUID string in the proper format/order */
477
478
AcpiOsPrintf (
479
"\"%2.2x%2.2x%2.2x%2.2x-"
480
"%2.2x%2.2x-"
481
"%2.2x%2.2x-"
482
"%2.2x%2.2x-"
483
"%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\")",
484
Data[3], Data[2], Data[1], Data[0],
485
Data[5], Data[4],
486
Data[7], Data[6],
487
Data[8], Data[9],
488
Data[10], Data[11], Data[12], Data[13], Data[14], Data[15]);
489
490
/* Dump the UUID description string if available */
491
492
Description = AcpiAhMatchUuid (Data);
493
if (Description)
494
{
495
AcpiOsPrintf (" /* %s */", Description);
496
}
497
else
498
{
499
AcpiOsPrintf (" /* Unknown UUID */");
500
}
501
}
502
503
504
/*******************************************************************************
505
*
506
* FUNCTION: AcpiDmIsUnicodeBuffer
507
*
508
* PARAMETERS: Op - Buffer Object to be examined
509
*
510
* RETURN: TRUE if buffer contains a UNICODE string
511
*
512
* DESCRIPTION: Determine if a buffer Op contains a Unicode string
513
*
514
******************************************************************************/
515
516
BOOLEAN
517
AcpiDmIsUnicodeBuffer (
518
ACPI_PARSE_OBJECT *Op)
519
{
520
UINT8 *ByteData;
521
UINT32 ByteCount;
522
UINT32 WordCount;
523
ACPI_PARSE_OBJECT *SizeOp;
524
ACPI_PARSE_OBJECT *NextOp;
525
UINT32 i;
526
527
528
/* Buffer size is the buffer argument */
529
530
SizeOp = Op->Common.Value.Arg;
531
if (!SizeOp)
532
{
533
return (FALSE);
534
}
535
536
/* Next, the initializer byte list to examine */
537
538
NextOp = SizeOp->Common.Next;
539
if (!NextOp)
540
{
541
return (FALSE);
542
}
543
544
/* Extract the byte list info */
545
546
ByteData = NextOp->Named.Data;
547
ByteCount = (UINT32) NextOp->Common.Value.Integer;
548
WordCount = ACPI_DIV_2 (ByteCount);
549
550
/*
551
* Unicode string must have an even number of bytes and last
552
* word must be zero
553
*/
554
if ((!ByteCount) ||
555
(ByteCount < 4) ||
556
(ByteCount & 1) ||
557
((UINT16 *) (void *) ByteData)[WordCount - 1] != 0)
558
{
559
return (FALSE);
560
}
561
562
/*
563
* For each word, 1st byte must be printable ascii, and the
564
* 2nd byte must be zero. This does not allow for escape
565
* sequences, but it is the most secure way to detect a
566
* unicode string.
567
*/
568
for (i = 0; i < (ByteCount - 2); i += 2)
569
{
570
if ((ByteData[i] == 0) ||
571
!(isprint (ByteData[i])) ||
572
(ByteData[(ACPI_SIZE) i + 1] != 0))
573
{
574
return (FALSE);
575
}
576
}
577
578
/* Ignore the Size argument in the disassembly of this buffer op */
579
580
SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
581
return (TRUE);
582
}
583
584
585
/*******************************************************************************
586
*
587
* FUNCTION: AcpiDmIsStringBuffer
588
*
589
* PARAMETERS: Op - Buffer Object to be examined
590
*
591
* RETURN: TRUE if buffer contains a ASCII string, FALSE otherwise
592
*
593
* DESCRIPTION: Determine if a buffer Op contains a ASCII string
594
*
595
******************************************************************************/
596
597
BOOLEAN
598
AcpiDmIsStringBuffer (
599
ACPI_PARSE_OBJECT *Op)
600
{
601
UINT8 *ByteData;
602
UINT32 ByteCount;
603
ACPI_PARSE_OBJECT *SizeOp;
604
ACPI_PARSE_OBJECT *NextOp;
605
UINT32 i;
606
607
608
/* Buffer size is the buffer argument */
609
610
SizeOp = Op->Common.Value.Arg;
611
if (!SizeOp)
612
{
613
return (FALSE);
614
}
615
616
/* Next, the initializer byte list to examine */
617
618
NextOp = SizeOp->Common.Next;
619
if (!NextOp)
620
{
621
return (FALSE);
622
}
623
624
/* Extract the byte list info */
625
626
ByteData = NextOp->Named.Data;
627
ByteCount = (UINT32) NextOp->Common.Value.Integer;
628
629
/* Last byte must be the null terminator */
630
631
if ((!ByteCount) ||
632
(ByteCount < 2) ||
633
(ByteData[ByteCount-1] != 0))
634
{
635
return (FALSE);
636
}
637
638
/*
639
* Check for a possible standalone resource EndTag, ignore it
640
* here. However, this sequence is also the string "Y", but
641
* this seems rare enough to be acceptable.
642
*/
643
if ((ByteCount == 2) && (ByteData[0] == 0x79))
644
{
645
return (FALSE);
646
}
647
648
/* Check all bytes for ASCII */
649
650
for (i = 0; i < (ByteCount - 1); i++)
651
{
652
/*
653
* TBD: allow some escapes (non-ascii chars).
654
* they will be handled in the string output routine
655
*/
656
657
/* Not a string if not printable ascii */
658
659
if (!isprint (ByteData[i]))
660
{
661
return (FALSE);
662
}
663
}
664
665
return (TRUE);
666
}
667
668
669
/*******************************************************************************
670
*
671
* FUNCTION: AcpiDmIsPldBuffer
672
*
673
* PARAMETERS: Op - Buffer Object to be examined
674
*
675
* RETURN: TRUE if buffer appears to contain data produced via the
676
* ToPLD macro, FALSE otherwise
677
*
678
* DESCRIPTION: Determine if a buffer Op contains a _PLD structure
679
*
680
******************************************************************************/
681
682
BOOLEAN
683
AcpiDmIsPldBuffer (
684
ACPI_PARSE_OBJECT *Op)
685
{
686
ACPI_NAMESPACE_NODE *Node;
687
ACPI_PARSE_OBJECT *SizeOp;
688
ACPI_PARSE_OBJECT *ByteListOp;
689
ACPI_PARSE_OBJECT *ParentOp;
690
UINT64 BufferSize;
691
UINT64 InitializerSize;
692
693
694
if (!Op)
695
{
696
return (FALSE);
697
}
698
699
/*
700
* Get the BufferSize argument - Buffer(BufferSize)
701
* If the buffer was generated by the ToPld macro, it must
702
* be a BYTE constant.
703
*/
704
SizeOp = Op->Common.Value.Arg;
705
if (!SizeOp || SizeOp->Common.AmlOpcode != AML_BYTE_OP)
706
{
707
return (FALSE);
708
}
709
710
/* Check the declared BufferSize, two possibilities */
711
712
BufferSize = SizeOp->Common.Value.Integer;
713
if ((BufferSize != ACPI_PLD_REV1_BUFFER_SIZE) &&
714
(BufferSize != ACPI_PLD_REV2_BUFFER_SIZE))
715
{
716
return (FALSE);
717
}
718
719
/*
720
* Check the initializer list length. This is the actual
721
* number of bytes in the buffer as counted by the AML parser.
722
* The declared BufferSize can be larger than the actual length.
723
* However, for the ToPLD macro, the BufferSize will be the same
724
* as the initializer list length.
725
*/
726
ByteListOp = SizeOp->Common.Next;
727
if (!ByteListOp)
728
{
729
return (FALSE); /* Zero-length buffer case */
730
}
731
732
InitializerSize = ByteListOp->Common.Value.Integer;
733
if ((InitializerSize != ACPI_PLD_REV1_BUFFER_SIZE) &&
734
(InitializerSize != ACPI_PLD_REV2_BUFFER_SIZE))
735
{
736
return (FALSE);
737
}
738
739
/* Final size check */
740
741
if (BufferSize != InitializerSize)
742
{
743
return (FALSE);
744
}
745
746
/* Now examine the buffer parent */
747
748
ParentOp = Op->Common.Parent;
749
if (!ParentOp)
750
{
751
return (FALSE);
752
}
753
754
/* Check for form: Name(_PLD, Buffer() {}). Not legal, however */
755
756
if (ParentOp->Common.AmlOpcode == AML_NAME_OP)
757
{
758
Node = ParentOp->Common.Node;
759
760
if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii, METHOD_NAME__PLD))
761
{
762
/* Ignore the Size argument in the disassembly of this buffer op */
763
764
SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
765
return (TRUE);
766
}
767
768
return (FALSE);
769
}
770
771
/*
772
* Check for proper form: Name(_PLD, Package() {ToPLD()})
773
*
774
* Note: All other forms such as
775
* Return (Package() {ToPLD()})
776
* Local0 = ToPLD()
777
* etc. are not converted back to the ToPLD macro, because
778
* there is really no deterministic way to disassemble the buffer
779
* back to the ToPLD macro, other than trying to find the "_PLD"
780
* name
781
*/
782
if (ParentOp->Common.AmlOpcode == AML_PACKAGE_OP)
783
{
784
ParentOp = ParentOp->Common.Parent;
785
if (!ParentOp)
786
{
787
return (FALSE);
788
}
789
790
if (ParentOp->Common.AmlOpcode == AML_NAME_OP)
791
{
792
Node = ParentOp->Common.Node;
793
794
if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii, METHOD_NAME__PLD))
795
{
796
/* Ignore the Size argument in the disassembly of this buffer op */
797
798
SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
799
return (TRUE);
800
}
801
}
802
}
803
804
return (FALSE);
805
}
806
807
808
/*******************************************************************************
809
*
810
* FUNCTION: AcpiDmFindNameByIndex
811
*
812
* PARAMETERS: Index - Index of array to check
813
* List - Array to reference
814
*
815
* RETURN: String from List or empty string
816
*
817
* DESCRIPTION: Finds and returns the char string located at the given index
818
* position in List.
819
*
820
******************************************************************************/
821
822
static const char *
823
AcpiDmFindNameByIndex (
824
UINT64 Index,
825
const char **List)
826
{
827
const char *NameString;
828
UINT32 i;
829
830
831
/* Bounds check */
832
833
NameString = List[0];
834
i = 0;
835
836
while (NameString)
837
{
838
i++;
839
NameString = List[i];
840
}
841
842
if (Index >= i)
843
{
844
/* TBD: Add error msg */
845
846
return ("");
847
}
848
849
return (List[Index]);
850
}
851
852
853
/*******************************************************************************
854
*
855
* FUNCTION: AcpiDmPldBuffer
856
*
857
* PARAMETERS: Level - Current source code indentation level
858
* ByteData - Pointer to the byte list
859
* ByteCount - Length of the byte list
860
*
861
* RETURN: None
862
*
863
* DESCRIPTION: Dump and format the contents of a _PLD buffer object
864
*
865
******************************************************************************/
866
867
#define ACPI_PLD_OUTPUT08 "%*.s%-22s = 0x%X,\n", ACPI_MUL_4 (Level), " "
868
#define ACPI_PLD_OUTPUT08P "%*.s%-22s = 0x%X)\n", ACPI_MUL_4 (Level), " "
869
#define ACPI_PLD_OUTPUT16 "%*.s%-22s = 0x%X,\n", ACPI_MUL_4 (Level), " "
870
#define ACPI_PLD_OUTPUT16P "%*.s%-22s = 0x%X)\n", ACPI_MUL_4 (Level), " "
871
#define ACPI_PLD_OUTPUT24 "%*.s%-22s = 0x%X,\n", ACPI_MUL_4 (Level), " "
872
#define ACPI_PLD_OUTPUTSTR "%*.s%-22s = \"%s\",\n", ACPI_MUL_4 (Level), " "
873
874
static void
875
AcpiDmPldBuffer (
876
UINT32 Level,
877
UINT8 *ByteData,
878
UINT32 ByteCount)
879
{
880
ACPI_PLD_INFO *PldInfo;
881
ACPI_STATUS Status;
882
883
884
/* Check for valid byte count */
885
886
if (ByteCount < ACPI_PLD_REV1_BUFFER_SIZE)
887
{
888
return;
889
}
890
891
/* Convert _PLD buffer to local _PLD struct */
892
893
Status = AcpiDecodePldBuffer (ByteData, ByteCount, &PldInfo);
894
if (ACPI_FAILURE (Status))
895
{
896
return;
897
}
898
899
AcpiOsPrintf ("\n");
900
901
/* First 32-bit dword */
902
903
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Revision", PldInfo->Revision);
904
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_IgnoreColor", PldInfo->IgnoreColor);
905
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Red", PldInfo->Red);
906
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Green", PldInfo->Green);
907
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Blue", PldInfo->Blue);
908
909
/* Second 32-bit dword */
910
911
AcpiOsPrintf (ACPI_PLD_OUTPUT16, "PLD_Width", PldInfo->Width);
912
AcpiOsPrintf (ACPI_PLD_OUTPUT16, "PLD_Height", PldInfo->Height);
913
914
/* Third 32-bit dword */
915
916
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_UserVisible", PldInfo->UserVisible);
917
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Dock", PldInfo->Dock);
918
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Lid", PldInfo->Lid);
919
AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_Panel",
920
AcpiDmFindNameByIndex(PldInfo->Panel, AcpiGbl_PldPanelList));
921
922
AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_VerticalPosition",
923
AcpiDmFindNameByIndex(PldInfo->VerticalPosition, AcpiGbl_PldVerticalPositionList));
924
925
AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_HorizontalPosition",
926
AcpiDmFindNameByIndex(PldInfo->HorizontalPosition, AcpiGbl_PldHorizontalPositionList));
927
928
AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_Shape",
929
AcpiDmFindNameByIndex(PldInfo->Shape, AcpiGbl_PldShapeList));
930
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_GroupOrientation", PldInfo->GroupOrientation);
931
932
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_GroupToken", PldInfo->GroupToken);
933
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_GroupPosition", PldInfo->GroupPosition);
934
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Bay", PldInfo->Bay);
935
936
/* Fourth 32-bit dword */
937
938
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Ejectable", PldInfo->Ejectable);
939
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_EjectRequired", PldInfo->OspmEjectRequired);
940
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_CabinetNumber", PldInfo->CabinetNumber);
941
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_CardCageNumber", PldInfo->CardCageNumber);
942
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Reference", PldInfo->Reference);
943
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Rotation", PldInfo->Rotation);
944
945
if (ByteCount >= ACPI_PLD_REV2_BUFFER_SIZE)
946
{
947
AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Order", PldInfo->Order);
948
949
/* Fifth 32-bit dword */
950
951
AcpiOsPrintf (ACPI_PLD_OUTPUT16, "PLD_VerticalOffset", PldInfo->VerticalOffset);
952
AcpiOsPrintf (ACPI_PLD_OUTPUT16P, "PLD_HorizontalOffset", PldInfo->HorizontalOffset);
953
}
954
else /* Rev 1 buffer */
955
{
956
AcpiOsPrintf (ACPI_PLD_OUTPUT08P, "PLD_Order", PldInfo->Order);
957
}
958
959
ACPI_FREE (PldInfo);
960
}
961
962
963
/*******************************************************************************
964
*
965
* FUNCTION: AcpiDmUnicode
966
*
967
* PARAMETERS: Op - Byte List op containing Unicode string
968
*
969
* RETURN: None
970
*
971
* DESCRIPTION: Dump Unicode string as a standard ASCII string. (Remove
972
* the extra zero bytes).
973
*
974
******************************************************************************/
975
976
static void
977
AcpiDmUnicode (
978
ACPI_PARSE_OBJECT *Op)
979
{
980
UINT16 *WordData;
981
UINT32 WordCount;
982
UINT32 i;
983
int OutputValue;
984
985
986
/* Extract the buffer info as a WORD buffer */
987
988
WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data);
989
WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer));
990
991
/* Write every other byte as an ASCII character */
992
993
AcpiOsPrintf ("\"");
994
for (i = 0; i < (WordCount - 1); i++)
995
{
996
OutputValue = (int) WordData[i];
997
998
/* Handle values that must be escaped */
999
1000
if ((OutputValue == '\"') ||
1001
(OutputValue == '\\'))
1002
{
1003
AcpiOsPrintf ("\\%c", OutputValue);
1004
}
1005
else if (!isprint (OutputValue))
1006
{
1007
AcpiOsPrintf ("\\x%2.2X", OutputValue);
1008
}
1009
else
1010
{
1011
AcpiOsPrintf ("%c", OutputValue);
1012
}
1013
}
1014
1015
AcpiOsPrintf ("\")");
1016
}
1017
1018
1019
/*******************************************************************************
1020
*
1021
* FUNCTION: AcpiDmGetHardwareIdType
1022
*
1023
* PARAMETERS: Op - Op to be examined
1024
*
1025
* RETURN: None
1026
*
1027
* DESCRIPTION: Determine the type of the argument to a _HID or _CID
1028
* 1) Strings are allowed
1029
* 2) If Integer, determine if it is a valid EISAID
1030
*
1031
******************************************************************************/
1032
1033
static void
1034
AcpiDmGetHardwareIdType (
1035
ACPI_PARSE_OBJECT *Op)
1036
{
1037
UINT32 BigEndianId;
1038
UINT32 Prefix[3];
1039
UINT32 i;
1040
1041
1042
switch (Op->Common.AmlOpcode)
1043
{
1044
case AML_STRING_OP:
1045
1046
/* Mark this string as an _HID/_CID string */
1047
1048
Op->Common.DisasmOpcode = ACPI_DASM_HID_STRING;
1049
break;
1050
1051
case AML_WORD_OP:
1052
case AML_DWORD_OP:
1053
1054
/* Determine if a Word/Dword is a valid encoded EISAID */
1055
1056
/* Swap from little-endian to big-endian to simplify conversion */
1057
1058
BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer);
1059
1060
/* Create the 3 leading ASCII letters */
1061
1062
Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40;
1063
Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40;
1064
Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40;
1065
1066
/* Verify that all 3 are ascii and alpha */
1067
1068
for (i = 0; i < 3; i++)
1069
{
1070
if (!ACPI_IS_ASCII (Prefix[i]) ||
1071
!isalpha (Prefix[i]))
1072
{
1073
return;
1074
}
1075
}
1076
1077
/* Mark this node as convertible to an EISA ID string */
1078
1079
Op->Common.DisasmOpcode = ACPI_DASM_EISAID;
1080
break;
1081
1082
default:
1083
break;
1084
}
1085
}
1086
1087
1088
/*******************************************************************************
1089
*
1090
* FUNCTION: AcpiDmCheckForHardwareId
1091
*
1092
* PARAMETERS: Op - Op to be examined
1093
*
1094
* RETURN: None
1095
*
1096
* DESCRIPTION: Determine if a Name() Op is a _HID/_CID.
1097
*
1098
******************************************************************************/
1099
1100
void
1101
AcpiDmCheckForHardwareId (
1102
ACPI_PARSE_OBJECT *Op)
1103
{
1104
UINT32 Name;
1105
ACPI_PARSE_OBJECT *NextOp;
1106
1107
1108
/* Get the NameSegment */
1109
1110
Name = AcpiPsGetName (Op);
1111
if (!Name)
1112
{
1113
return;
1114
}
1115
1116
NextOp = AcpiPsGetDepthNext (NULL, Op);
1117
if (!NextOp)
1118
{
1119
return;
1120
}
1121
1122
/* Check for _HID - has one argument */
1123
1124
if (ACPI_COMPARE_NAMESEG (&Name, METHOD_NAME__HID))
1125
{
1126
AcpiDmGetHardwareIdType (NextOp);
1127
return;
1128
}
1129
1130
/* Exit if not _CID */
1131
1132
if (!ACPI_COMPARE_NAMESEG (&Name, METHOD_NAME__CID))
1133
{
1134
return;
1135
}
1136
1137
/* _CID can contain a single argument or a package */
1138
1139
if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP)
1140
{
1141
AcpiDmGetHardwareIdType (NextOp);
1142
return;
1143
}
1144
1145
/* _CID with Package: get the package length, check all elements */
1146
1147
NextOp = AcpiPsGetDepthNext (NULL, NextOp);
1148
if (!NextOp)
1149
{
1150
return;
1151
}
1152
1153
/* Don't need to use the length, just walk the peer list */
1154
1155
NextOp = NextOp->Common.Next;
1156
while (NextOp)
1157
{
1158
AcpiDmGetHardwareIdType (NextOp);
1159
NextOp = NextOp->Common.Next;
1160
}
1161
}
1162
1163
1164
/*******************************************************************************
1165
*
1166
* FUNCTION: AcpiDmDecompressEisaId
1167
*
1168
* PARAMETERS: EncodedId - Raw encoded EISA ID.
1169
*
1170
* RETURN: None
1171
*
1172
* DESCRIPTION: Convert an encoded EISAID back to the original ASCII String
1173
* and emit the correct ASL statement. If the ID is known, emit
1174
* a description of the ID as a comment.
1175
*
1176
******************************************************************************/
1177
1178
void
1179
AcpiDmDecompressEisaId (
1180
UINT32 EncodedId)
1181
{
1182
char IdBuffer[ACPI_EISAID_STRING_SIZE];
1183
const AH_DEVICE_ID *Info;
1184
1185
1186
/* Convert EISAID to a string an emit the statement */
1187
1188
AcpiExEisaIdToString (IdBuffer, EncodedId);
1189
AcpiOsPrintf ("EisaId (\"%s\")", IdBuffer);
1190
1191
/* If we know about the ID, emit the description */
1192
1193
Info = AcpiAhMatchHardwareId (IdBuffer);
1194
if (Info)
1195
{
1196
AcpiOsPrintf (" /* %s */", Info->Description);
1197
}
1198
}
1199
1200