]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelper.c
DynamicTablesPkg: Add AmlGetEisaIdFromString() to AcpiHelperLib
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AcpiHelperLib / AcpiHelper.c
1 /** @file
2 Acpi Helper
3
4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <Library/BaseLib.h>
10 #include <Library/DebugLib.h>
11
12 // Module specific include files.
13 #include <Library/AcpiHelperLib.h>
14
15 /** Convert a hex number to its ASCII code.
16
17 @param [in] Hex Hex number to convert.
18 Must be 0 <= x < 16.
19
20 @return The ASCII code corresponding to x.
21 -1 if error.
22 **/
23 UINT8
24 EFIAPI
25 AsciiFromHex (
26 IN UINT8 Hex
27 )
28 {
29 if (Hex < 10) {
30 return (UINT8)(Hex + '0');
31 }
32
33 if (Hex < 16) {
34 return (UINT8)(Hex - 10 + 'A');
35 }
36
37 ASSERT (FALSE);
38 return (UINT8)-1;
39 }
40
41 /** Convert an ASCII char representing an hexadecimal number
42 to its integer value.
43
44 @param [in] Char Char to convert.
45 Must be between '0'-'9' or 'A'-'F' or 'a'-'f'.
46
47 @return The corresponding integer (between 0-16).
48 -1 if error.
49 **/
50 UINT8
51 EFIAPI
52 HexFromAscii (
53 IN CHAR8 Char
54 )
55 {
56 if ((Char >= '0') && (Char <= '9')) {
57 return (UINT8)(Char - '0');
58 }
59
60 if ((Char >= 'A') && (Char <= 'F')) {
61 return (UINT8)(Char - 'A' + 10);
62 }
63
64 if ((Char >= 'a') && (Char <= 'f')) {
65 return (UINT8)(Char - 'a' + 10);
66 }
67
68 ASSERT (FALSE);
69 return (UINT8)-1;
70 }
71
72 /** Check if a HID is a valid PNP ID.
73
74 @param [in] Hid The Hid to validate.
75
76 @retval TRUE The Hid is a valid PNP ID.
77 @retval FALSE The Hid is not a valid PNP ID.
78 **/
79 BOOLEAN
80 IsValidPnpId (
81 IN CONST CHAR8 * Hid
82 )
83 {
84 UINTN Index;
85
86 if (AsciiStrLen (Hid) != 7) {
87 return FALSE;
88 }
89
90 // A valid PNP ID must be of the form "AAA####"
91 // where A is an uppercase letter and # is a hex digit.
92 for (Index = 0; Index < 3; Index++) {
93 if (!IS_UPPER_CHAR (Hid[Index])) {
94 return FALSE;
95 }
96 }
97
98 for (Index = 3; Index < 7; Index++) {
99 if (!IS_UPPER_HEX (Hid[Index])) {
100 return FALSE;
101 }
102 }
103
104 return TRUE;
105 }
106
107 /** Check if a HID is a valid ACPI ID.
108
109 @param [in] Hid The Hid to validate.
110
111 @retval TRUE The Hid is a valid ACPI ID.
112 @retval FALSE The Hid is not a valid ACPI ID.
113 **/
114 BOOLEAN
115 IsValidAcpiId (
116 IN CONST CHAR8 * Hid
117 )
118 {
119 UINTN Index;
120
121 if (AsciiStrLen (Hid) != 8) {
122 return FALSE;
123 }
124
125 // A valid ACPI ID must be of the form "NNNN####"
126 // where N is an uppercase letter or a digit ('0'-'9')
127 // and # is a hex digit.
128 for (Index = 0; Index < 4; Index++) {
129 if (!(IS_UPPER_CHAR (Hid[Index]) || IS_DIGIT (Hid[Index]))) {
130 return FALSE;
131 }
132 }
133
134 for (Index = 4; Index < 8; Index++) {
135 if (!IS_UPPER_HEX (Hid[Index])) {
136 return FALSE;
137 }
138 }
139
140 return TRUE;
141 }
142
143 /** Convert a EisaId string to its compressed UINT32 equivalent.
144
145 Cf. ACPI 6.4 specification, s19.3.4 "ASL Macros": "Eisaid"
146
147 @param [in] EisaIdStr Input EisaId string.
148 @param [out] EisaIdInt Output EisaId UINT32 (compressed).
149
150 @retval EFI_SUCCESS The function completed successfully.
151 @retval EFI_INVALID_PARAMETER Invalid parameter.
152 **/
153 EFI_STATUS
154 EFIAPI
155 AmlGetEisaIdFromString (
156 IN CONST CHAR8 * EisaIdStr,
157 OUT UINT32 * EisaIdInt
158 )
159 {
160 if ((EisaIdStr == NULL) ||
161 (!IsValidPnpId (EisaIdStr)) ||
162 (EisaIdInt == NULL)) {
163 ASSERT (0);
164 return EFI_INVALID_PARAMETER;
165 }
166
167 /* Cf. ACPI 6.4 specification, s19.3.4 "ASL Macros": "Eisaid"
168
169 Converts and compresses the 7-character text argument into its corresponding
170 4-byte numeric EISA ID encoding (Integer). This can be used when declaring
171 IDs for devices that are EISA IDs.
172
173 The algorithm used to convert the TextID is as shown in the following
174 example:
175 Starting with a seven character input string "PNP0303", we want to create
176 a DWordConst. This string contains a three character manufacturer code
177 "PNP", a three character hex product identifier "030", and a one character
178 revision identifier "3".
179 The compressed manufacturer code is created as follows:
180 1) Find hex ASCII value for each letter
181 2) Subtract 40h from each ASCII value
182 3) Retain 5 least significant bits for each letter and discard remaining
183 0's:
184
185 Byte 0:
186 Bit 7: reserved (0)
187 Bit 6-2: 1st character of compressed mfg code "P"
188 Bit 1-0: Upper 2 bits of 2nd character of mfg code "N"
189 Byte 1:
190 Bit 7-5: Lower 3 bits of 2nd character of mfg code "N"
191 Bit 4-0: 3rd character of mfg code "P"
192 Byte 2:
193 Bit 7-4: 1st hex digit of product number "0"
194 Bit 3-0: 2nd hex digit of product number "3"
195 Byte 3:
196 Bit 7-4: 3rd hex digit of product number "0"
197 Bit 3-0: 4th hex digit of product number "3"
198 */
199 *EisaIdInt = SwapBytes32 (
200 ((EisaIdStr[0] - 0x40) << 26) |
201 ((EisaIdStr[1] - 0x40) << 21) |
202 ((EisaIdStr[2] - 0x40) << 16) |
203 (HexFromAscii (EisaIdStr[3]) << 12) |
204 (HexFromAscii (EisaIdStr[4]) << 8) |
205 (HexFromAscii (EisaIdStr[5]) << 4) |
206 (HexFromAscii (EisaIdStr[6]))
207 );
208
209 return EFI_SUCCESS;
210 }