1 /********************************************************************************
2 Copyright (C) 2016 Marvell International Ltd.
3
4 Marvell BSD License Option
5
6 If you received this File from Marvell, you may opt to use, redistribute and/or
7 modify this File under the following licensing terms.
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11 * Redistributions of source code must Retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13
14 * Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
17
18 * Neither the name of Marvell nor the names of its contributors may be
19 used to endorse or promote products derived from this software without
20 specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 *******************************************************************************/
34 #define CHAR_NULL 0x0000
35
36 #include <Library/BaseLib.h>
37 #include <Uefi.h>
38 #include <Library/UefiLib.h>
39 #include <Library/DebugLib.h>
40
41 STATIC
42 CHAR16
CharToUpper(IN CHAR16 Char)43 CharToUpper (
44 IN CHAR16 Char
45 )
46 {
47
48 if (Char >= L'a' && Char <= L'z') {
49 return (CHAR16) (Char - (L'a' - L'A'));
50 }
51
52 return Char;
53 }
54
55 STATIC
56 BOOLEAN
IsDecimalDigitChar(IN CHAR16 Char)57 IsDecimalDigitChar (
58 IN CHAR16 Char
59 )
60 {
61
62 return (BOOLEAN) (Char >= L'0' && Char <= L'9');
63 }
64
65
66 STATIC
67 UINTN
HexCharToUintn(IN CHAR16 Char)68 HexCharToUintn (
69 IN CHAR16 Char
70 )
71 {
72 if (IsDecimalDigitChar (Char)) {
73 return Char - L'0';
74 }
75
76 return (UINTN) (10 + CharToUpper (Char) - L'A');
77 }
78
79 STATIC
80 BOOLEAN
IsHexDigitCharacter(CHAR16 Char)81 IsHexDigitCharacter (
82 CHAR16 Char
83 )
84 {
85
86 return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' &&
87 Char <= L'F') || (Char >= L'a' && Char <= L'f'));
88 }
89
90 STATIC
91 UINTN
HexStrToUintn(CHAR16 * String)92 HexStrToUintn (
93 CHAR16 *String
94 )
95 {
96 UINTN Result = 0;
97
98 if (String == NULL || StrSize(String) == 0) {
99 return (UINTN)(-1);
100 }
101
102 // Ignore spaces and tabs
103 while ((*String == L' ') || (*String == L'\t')) {
104 String++;
105 }
106
107 // Ignore leading zeros after spaces
108 while (*String == L'0') {
109 String++;
110 }
111
112 if (CharToUpper (*String) != L'X') {
113 return (UINTN)(-1);
114 }
115
116 // Skip 'x'
117 String++;
118
119 while (IsHexDigitCharacter (*String)) {
120 Result <<= 4;
121 Result += HexCharToUintn (*String);
122 String++;
123 }
124
125 return (UINTN) Result;
126 }
127
128 STATIC
129 UINTN
DecimalStrToUintn(CHAR16 * String)130 DecimalStrToUintn (
131 CHAR16 *String
132 )
133 {
134 UINTN Result = 0;
135
136 while (IsDecimalDigitChar (*String)) {
137 Result = 10 * Result + (*String - L'0');
138 String++;
139 }
140
141 return Result;
142 }
143
144 STATIC
145 UINTN
StrToUintn(CHAR16 * String)146 StrToUintn (
147 CHAR16 *String
148 )
149 {
150 CHAR16 *Walker;
151
152 // Chop off leading spaces
153 for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);
154
155 if (StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0) {
156 return HexStrToUintn (Walker);
157 } else {
158 return DecimalStrToUintn (Walker);
159 }
160 }
161
162 EFI_STATUS
ParsePcdString(IN CHAR16 * PcdString,IN UINT8 Count,OUT UINTN * ValueTable,OUT CHAR16 ** StrTable)163 ParsePcdString (
164 IN CHAR16 *PcdString,
165 IN UINT8 Count,
166 OUT UINTN *ValueTable,
167 OUT CHAR16 **StrTable
168 )
169 {
170 BOOLEAN ValueFlag = FALSE;
171 CHAR16 *Walker;
172 UINTN i, Tmp = 0;
173
174 if (ValueTable != NULL) {
175 ValueFlag = TRUE;
176 }
177
178 // Set pointer at the end of PCD string
179 Walker = PcdString + StrLen (PcdString);
180 for (i = 0; i < Count; i++) {
181 while ((--Walker) >= PcdString) {
182 if (*Walker == L';') {
183 // Cut off parsed chunk from PCD string by replacing ';' with
184 // null-terminator
185 *Walker = '\0';
186 if (ValueFlag) {
187 Tmp = StrToUintn ((Walker + 1));
188 if ((UINTN)(-1) == Tmp) {
189 return EFI_INVALID_PARAMETER;
190 }
191 // Entry is parsed from the end to the beginning
192 // so fill table in the same manner
193 ValueTable[Count - (i + 1)] = Tmp;
194 } else {
195 StrTable[Count - (i + 1)] = Walker + 1;
196 }
197 Walker--;
198 break;
199 }
200 if (Walker == PcdString) {
201 if (ValueFlag) {
202 Tmp = StrToUintn ((Walker));
203 if (Tmp == (UINTN)(-1)) {
204 return EFI_INVALID_PARAMETER;
205 }
206 }
207 // Last device's entry should be added to the table here.
208 // If not, return error
209 if (i != (Count - 1)) {
210 DEBUG((DEBUG_ERROR, "ParsePcdLib: Please set PCD value for every "
211 "device\n"));
212 return EFI_INVALID_PARAMETER;
213 }
214 // We parse from the end to the beginning
215 // so fill table in the same manner
216 if (ValueFlag) {
217 ValueTable[Count - (i + 1)] = Tmp;
218 } else {
219 StrTable[Count - (i + 1)] = Walker;
220 }
221 // End both loops
222 return EFI_SUCCESS;
223 }
224 }
225 }
226
227 return EFI_SUCCESS;
228 }
229