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