]>
Commit | Line | Data |
---|---|---|
e52c5a9f | 1 | /** @file |
ad1b3619 | 2 | Utility functions which helps in opcode creation, HII configuration string manipulations, |
3 | pop up window creations, setup browser persistence data set and get. | |
e52c5a9f | 4 | |
54cf8780 | 5 | Copyright (c) 2007- 2008, Intel Corporation |
e52c5a9f | 6 | All rights reserved. This program and the accompanying materials |
7 | are licensed and made available under the terms and conditions of the BSD License | |
8 | which accompanies this distribution. The full text of the license may be found at | |
9 | http://opensource.org/licenses/bsd-license.php | |
10 | ||
11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
13 | ||
e52c5a9f | 14 | **/ |
15 | ||
16 | #include "UefiIfrLibraryInternal.h" | |
17 | ||
18 | // | |
19 | // Fake <ConfigHdr> | |
20 | // | |
1db1f6ad | 21 | GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0"; |
e52c5a9f | 22 | |
e52c5a9f | 23 | /** |
24 | Draw a dialog and return the selected key. | |
25 | ||
26 | @param NumberOfLines The number of lines for the dialog box | |
27 | @param KeyValue The EFI_KEY value returned if HotKey is TRUE.. | |
28 | @param String Pointer to the first string in the list | |
1db1f6ad | 29 | @param ... A series of (quantity == NumberOfLines - 1) text |
e52c5a9f | 30 | strings which will be used to construct the dialog |
31 | box | |
32 | ||
33 | @retval EFI_SUCCESS Displayed dialog and received user interaction | |
34 | @retval EFI_INVALID_PARAMETER One of the parameters was invalid. | |
35 | ||
36 | **/ | |
37 | EFI_STATUS | |
38 | EFIAPI | |
39 | IfrLibCreatePopUp ( | |
40 | IN UINTN NumberOfLines, | |
41 | OUT EFI_INPUT_KEY *KeyValue, | |
42 | IN CHAR16 *String, | |
43 | ... | |
44 | ) | |
45 | { | |
46 | UINTN Index; | |
47 | UINTN Count; | |
48 | UINTN Start; | |
49 | UINTN Top; | |
50 | CHAR16 *StringPtr; | |
51 | UINTN LeftColumn; | |
52 | UINTN RightColumn; | |
53 | UINTN TopRow; | |
54 | UINTN BottomRow; | |
55 | UINTN DimensionsWidth; | |
56 | UINTN DimensionsHeight; | |
57 | VA_LIST Marker; | |
58 | EFI_INPUT_KEY Key; | |
59 | UINTN LargestString; | |
60 | CHAR16 *StackString; | |
61 | EFI_STATUS Status; | |
62 | UINTN StringLen; | |
63 | CHAR16 *LineBuffer; | |
64 | CHAR16 **StringArray; | |
65 | EFI_EVENT TimerEvent; | |
66 | EFI_EVENT WaitList[2]; | |
67 | UINTN CurrentAttribute; | |
68 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; | |
69 | ||
70 | if ((KeyValue == NULL) || (String == NULL)) { | |
71 | return EFI_INVALID_PARAMETER; | |
72 | } | |
73 | ||
74 | TopRow = 0; | |
75 | BottomRow = 0; | |
76 | LeftColumn = 0; | |
77 | RightColumn = 0; | |
78 | ||
79 | ConOut = gST->ConOut; | |
80 | ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow); | |
81 | ||
82 | DimensionsWidth = RightColumn - LeftColumn; | |
83 | DimensionsHeight = BottomRow - TopRow; | |
84 | ||
85 | CurrentAttribute = ConOut->Mode->Attribute; | |
86 | ||
87 | LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16)); | |
88 | ASSERT (LineBuffer != NULL); | |
89 | ||
90 | // | |
91 | // Determine the largest string in the dialog box | |
92 | // Notice we are starting with 1 since String is the first string | |
93 | // | |
94 | StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *)); | |
95 | LargestString = StrLen (String); | |
96 | StringArray[0] = String; | |
97 | ||
98 | VA_START (Marker, String); | |
99 | for (Index = 1; Index < NumberOfLines; Index++) { | |
100 | StackString = VA_ARG (Marker, CHAR16 *); | |
101 | ||
102 | if (StackString == NULL) { | |
103 | return EFI_INVALID_PARAMETER; | |
104 | } | |
105 | ||
106 | StringArray[Index] = StackString; | |
107 | StringLen = StrLen (StackString); | |
108 | if (StringLen > LargestString) { | |
109 | LargestString = StringLen; | |
110 | } | |
111 | } | |
1db1f6ad | 112 | VA_END (Marker); |
e52c5a9f | 113 | |
114 | if ((LargestString + 2) > DimensionsWidth) { | |
115 | LargestString = DimensionsWidth - 2; | |
116 | } | |
117 | ||
118 | // | |
119 | // Subtract the PopUp width from total Columns, allow for one space extra on | |
120 | // each end plus a border. | |
121 | // | |
122 | Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1; | |
123 | ||
124 | Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1; | |
125 | ||
126 | // | |
127 | // Disable cursor | |
128 | // | |
129 | ConOut->EnableCursor (ConOut, FALSE); | |
130 | ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); | |
131 | ||
132 | StringPtr = &LineBuffer[0]; | |
133 | *StringPtr++ = BOXDRAW_DOWN_RIGHT; | |
134 | for (Index = 0; Index < LargestString; Index++) { | |
135 | *StringPtr++ = BOXDRAW_HORIZONTAL; | |
136 | } | |
137 | *StringPtr++ = BOXDRAW_DOWN_LEFT; | |
138 | *StringPtr = L'\0'; | |
139 | ||
140 | ConOut->SetCursorPosition (ConOut, Start, Top); | |
141 | ConOut->OutputString (ConOut, LineBuffer); | |
142 | ||
143 | for (Index = 0; Index < NumberOfLines; Index++) { | |
144 | StringPtr = &LineBuffer[0]; | |
145 | *StringPtr++ = BOXDRAW_VERTICAL; | |
146 | ||
147 | for (Count = 0; Count < LargestString; Count++) { | |
148 | StringPtr[Count] = L' '; | |
149 | } | |
150 | ||
151 | StringLen = StrLen (StringArray[Index]); | |
152 | if (StringLen > LargestString) { | |
153 | StringLen = LargestString; | |
154 | } | |
155 | CopyMem ( | |
156 | StringPtr + ((LargestString - StringLen) / 2), | |
157 | StringArray[Index], | |
158 | StringLen * sizeof (CHAR16) | |
159 | ); | |
160 | StringPtr += LargestString; | |
161 | ||
162 | *StringPtr++ = BOXDRAW_VERTICAL; | |
163 | *StringPtr = L'\0'; | |
164 | ||
165 | ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index); | |
166 | ConOut->OutputString (ConOut, LineBuffer); | |
167 | } | |
168 | ||
169 | StringPtr = &LineBuffer[0]; | |
170 | *StringPtr++ = BOXDRAW_UP_RIGHT; | |
171 | for (Index = 0; Index < LargestString; Index++) { | |
172 | *StringPtr++ = BOXDRAW_HORIZONTAL; | |
173 | } | |
174 | *StringPtr++ = BOXDRAW_UP_LEFT; | |
175 | *StringPtr = L'\0'; | |
176 | ||
177 | ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1); | |
178 | ConOut->OutputString (ConOut, LineBuffer); | |
179 | ||
180 | do { | |
181 | Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); | |
182 | ||
183 | // | |
184 | // Set a timer event of 1 second expiration | |
185 | // | |
186 | gBS->SetTimer ( | |
187 | TimerEvent, | |
188 | TimerRelative, | |
189 | 10000000 | |
190 | ); | |
191 | ||
192 | // | |
193 | // Wait for the keystroke event or the timer | |
194 | // | |
195 | WaitList[0] = gST->ConIn->WaitForKey; | |
196 | WaitList[1] = TimerEvent; | |
197 | Status = gBS->WaitForEvent (2, WaitList, &Index); | |
198 | ||
199 | // | |
200 | // Check for the timer expiration | |
201 | // | |
202 | if (!EFI_ERROR (Status) && Index == 1) { | |
203 | Status = EFI_TIMEOUT; | |
204 | } | |
205 | ||
206 | gBS->CloseEvent (TimerEvent); | |
207 | } while (Status == EFI_TIMEOUT); | |
208 | ||
209 | Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); | |
210 | CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY)); | |
211 | ||
212 | ConOut->SetAttribute (ConOut, CurrentAttribute); | |
213 | ConOut->EnableCursor (ConOut, TRUE); | |
214 | ||
215 | return Status; | |
216 | } | |
217 | ||
218 | ||
219 | /** | |
ad1b3619 | 220 | Swap bytes in the buffer. This is a internal function. |
e52c5a9f | 221 | |
222 | @param Buffer Binary buffer. | |
223 | @param BufferSize Size of the buffer in bytes. | |
224 | ||
225 | @return None. | |
226 | ||
227 | **/ | |
e52c5a9f | 228 | VOID |
229 | SwapBuffer ( | |
230 | IN OUT UINT8 *Buffer, | |
231 | IN UINTN BufferSize | |
232 | ) | |
233 | { | |
234 | UINTN Index; | |
235 | UINT8 Temp; | |
236 | UINTN SwapCount; | |
237 | ||
54cf8780 | 238 | SwapCount = BufferSize / 2; |
e52c5a9f | 239 | for (Index = 0; Index < SwapCount; Index++) { |
240 | Temp = Buffer[Index]; | |
241 | Buffer[Index] = Buffer[BufferSize - 1 - Index]; | |
242 | Buffer[BufferSize - 1 - Index] = Temp; | |
243 | } | |
244 | } | |
245 | ||
54cf8780 | 246 | /** |
247 | Converts the unicode character of the string from uppercase to lowercase. | |
ad1b3619 | 248 | This is a internal function. |
54cf8780 | 249 | |
250 | @param Str String to be converted | |
251 | ||
54cf8780 | 252 | **/ |
253 | VOID | |
1db1f6ad | 254 | EFIAPI |
54cf8780 | 255 | ToLower ( |
256 | IN OUT CHAR16 *Str | |
257 | ) | |
258 | { | |
259 | CHAR16 *Ptr; | |
260 | ||
261 | for (Ptr = Str; *Ptr != L'\0'; Ptr++) { | |
262 | if (*Ptr >= L'A' && *Ptr <= L'Z') { | |
263 | *Ptr = (CHAR16) (*Ptr - L'A' + L'a'); | |
264 | } | |
265 | } | |
266 | } | |
267 | ||
e52c5a9f | 268 | |
269 | /** | |
d9e5c1ff | 270 | Converts binary buffer to Unicode string in reversed byte order from BufToHexString(). |
e52c5a9f | 271 | |
272 | @param Str String for output | |
273 | @param Buffer Binary buffer. | |
274 | @param BufferSize Size of the buffer in bytes. | |
275 | ||
276 | @retval EFI_SUCCESS The function completed successfully. | |
277 | ||
278 | **/ | |
279 | EFI_STATUS | |
280 | EFIAPI | |
281 | BufferToHexString ( | |
282 | IN OUT CHAR16 *Str, | |
283 | IN UINT8 *Buffer, | |
284 | IN UINTN BufferSize | |
285 | ) | |
286 | { | |
287 | EFI_STATUS Status; | |
288 | UINT8 *NewBuffer; | |
289 | UINTN StrBufferLen; | |
290 | ||
291 | NewBuffer = AllocateCopyPool (BufferSize, Buffer); | |
292 | SwapBuffer (NewBuffer, BufferSize); | |
293 | ||
54cf8780 | 294 | StrBufferLen = BufferSize * sizeof (CHAR16) + 1; |
d9e5c1ff | 295 | Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize); |
e52c5a9f | 296 | |
1db1f6ad | 297 | FreePool (NewBuffer); |
54cf8780 | 298 | // |
299 | // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format. | |
300 | // | |
301 | ToLower (Str); | |
e52c5a9f | 302 | |
303 | return Status; | |
304 | } | |
305 | ||
306 | ||
307 | /** | |
d9e5c1ff | 308 | Converts Hex String to binary buffer in reversed byte order from HexStringToBuf(). |
e52c5a9f | 309 | |
310 | @param Buffer Pointer to buffer that receives the data. | |
311 | @param BufferSize Length in bytes of the buffer to hold converted | |
312 | data. If routine return with EFI_SUCCESS, | |
313 | containing length of converted data. If routine | |
314 | return with EFI_BUFFER_TOO_SMALL, containg length | |
315 | of buffer desired. | |
316 | @param Str String to be converted from. | |
317 | ||
318 | @retval EFI_SUCCESS The function completed successfully. | |
319 | ||
320 | **/ | |
321 | EFI_STATUS | |
322 | EFIAPI | |
323 | HexStringToBuffer ( | |
324 | IN OUT UINT8 *Buffer, | |
325 | IN OUT UINTN *BufferSize, | |
326 | IN CHAR16 *Str | |
327 | ) | |
328 | { | |
329 | EFI_STATUS Status; | |
330 | UINTN ConvertedStrLen; | |
331 | ||
332 | ConvertedStrLen = 0; | |
d9e5c1ff | 333 | Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen); |
e52c5a9f | 334 | if (!EFI_ERROR (Status)) { |
335 | SwapBuffer (Buffer, ConvertedStrLen); | |
336 | } | |
337 | ||
338 | return Status; | |
339 | } | |
340 | ||
54cf8780 | 341 | /** |
342 | Convert binary representation Config string (e.g. "0041004200430044") to the | |
343 | original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e. | |
344 | "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). | |
345 | ||
346 | @param UnicodeString Original Unicode string. | |
347 | @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string. | |
348 | Includes tailing '\0' character. | |
349 | On output: | |
350 | If return EFI_SUCCESS, containing length of Unicode string buffer. | |
351 | If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. | |
352 | @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+ | |
353 | ||
354 | @retval EFI_SUCCESS Routine success. | |
355 | @retval EFI_BUFFER_TOO_SMALL The string buffer is too small. | |
356 | ||
357 | **/ | |
358 | EFI_STATUS | |
1db1f6ad | 359 | EFIAPI |
54cf8780 | 360 | ConfigStringToUnicode ( |
361 | IN OUT CHAR16 *UnicodeString, | |
362 | IN OUT UINTN *StrBufferLen, | |
363 | IN CHAR16 *ConfigString | |
364 | ) | |
365 | { | |
366 | UINTN Index; | |
367 | UINTN Len; | |
368 | UINTN BufferSize; | |
369 | CHAR16 BackupChar; | |
370 | ||
371 | Len = StrLen (ConfigString) / 4; | |
372 | BufferSize = (Len + 1) * sizeof (CHAR16); | |
373 | ||
374 | if (*StrBufferLen < BufferSize) { | |
375 | *StrBufferLen = BufferSize; | |
376 | return EFI_BUFFER_TOO_SMALL; | |
377 | } | |
378 | ||
379 | *StrBufferLen = BufferSize; | |
380 | ||
381 | for (Index = 0; Index < Len; Index++) { | |
382 | BackupChar = ConfigString[4]; | |
383 | ConfigString[4] = L'\0'; | |
384 | ||
385 | HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL); | |
386 | ||
387 | ConfigString[4] = BackupChar; | |
388 | ||
389 | ConfigString += 4; | |
390 | UnicodeString += 1; | |
391 | } | |
392 | ||
393 | // | |
394 | // Add tailing '\0' character | |
395 | // | |
396 | *UnicodeString = L'\0'; | |
397 | ||
398 | return EFI_SUCCESS; | |
399 | } | |
400 | ||
401 | /** | |
402 | Convert Unicode string to binary representation Config string, e.g. | |
403 | "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e. | |
404 | "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). | |
405 | ||
406 | @param ConfigString Binary representation of Unicode String, <string> := (<HexCh>4)+ | |
407 | @param StrBufferLen On input: Length in bytes of buffer to hold the Unicode string. | |
408 | Includes tailing '\0' character. | |
409 | On output: | |
410 | If return EFI_SUCCESS, containing length of Unicode string buffer. | |
411 | If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. | |
412 | @param UnicodeString Original Unicode string. | |
413 | ||
414 | @retval EFI_SUCCESS Routine success. | |
415 | @retval EFI_BUFFER_TOO_SMALL The string buffer is too small. | |
416 | ||
417 | **/ | |
418 | EFI_STATUS | |
1db1f6ad | 419 | EFIAPI |
54cf8780 | 420 | UnicodeToConfigString ( |
421 | IN OUT CHAR16 *ConfigString, | |
422 | IN OUT UINTN *StrBufferLen, | |
423 | IN CHAR16 *UnicodeString | |
424 | ) | |
425 | { | |
426 | UINTN Index; | |
427 | UINTN Len; | |
428 | UINTN BufferSize; | |
429 | CHAR16 *String; | |
430 | ||
431 | Len = StrLen (UnicodeString); | |
432 | BufferSize = (Len * 4 + 1) * sizeof (CHAR16); | |
433 | ||
434 | if (*StrBufferLen < BufferSize) { | |
435 | *StrBufferLen = BufferSize; | |
436 | return EFI_BUFFER_TOO_SMALL; | |
437 | } | |
438 | ||
439 | *StrBufferLen = BufferSize; | |
440 | String = ConfigString; | |
441 | ||
442 | for (Index = 0; Index < Len; Index++) { | |
443 | BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2); | |
444 | ||
445 | ConfigString += 4; | |
446 | UnicodeString += 1; | |
447 | } | |
448 | ||
449 | // | |
450 | // Add tailing '\0' character | |
451 | // | |
452 | *ConfigString = L'\0'; | |
453 | ||
454 | // | |
455 | // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format. | |
456 | // | |
457 | ToLower (String); | |
458 | return EFI_SUCCESS; | |
459 | } | |
e52c5a9f | 460 | |
461 | /** | |
462 | Construct <ConfigHdr> using routing information GUID/NAME/PATH. | |
463 | ||
464 | @param ConfigHdr Pointer to the ConfigHdr string. | |
465 | @param StrBufferLen On input: Length in bytes of buffer to hold the | |
466 | ConfigHdr string. Includes tailing '\0' character. | |
467 | On output: If return EFI_SUCCESS, containing | |
468 | length of ConfigHdr string buffer. If return | |
469 | EFI_BUFFER_TOO_SMALL, containg length of string | |
470 | buffer desired. | |
471 | @param Guid Routing information: GUID. | |
472 | @param Name Routing information: NAME. | |
473 | @param DriverHandle Driver handle which contains the routing | |
474 | information: PATH. | |
475 | ||
476 | @retval EFI_SUCCESS Routine success. | |
477 | @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small. | |
478 | ||
479 | **/ | |
480 | EFI_STATUS | |
481 | EFIAPI | |
482 | ConstructConfigHdr ( | |
483 | IN OUT CHAR16 *ConfigHdr, | |
484 | IN OUT UINTN *StrBufferLen, | |
485 | IN EFI_GUID *Guid, | |
486 | IN CHAR16 *Name, OPTIONAL | |
487 | IN EFI_HANDLE *DriverHandle | |
488 | ) | |
489 | { | |
490 | EFI_STATUS Status; | |
491 | UINTN NameStrLen; | |
492 | UINTN DevicePathSize; | |
493 | UINTN BufferSize; | |
494 | CHAR16 *StrPtr; | |
495 | EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
496 | ||
497 | if (Name == NULL) { | |
498 | // | |
499 | // There will be no "NAME" in <ConfigHdr> for Name/Value storage | |
500 | // | |
501 | NameStrLen = 0; | |
502 | } else { | |
503 | // | |
504 | // For buffer storage | |
505 | // | |
506 | NameStrLen = StrLen (Name); | |
507 | } | |
508 | ||
509 | // | |
510 | // Retrieve DevicePath Protocol associated with this HiiPackageList | |
511 | // | |
512 | Status = gBS->HandleProtocol ( | |
513 | DriverHandle, | |
514 | &gEfiDevicePathProtocolGuid, | |
515 | (VOID **) &DevicePath | |
516 | ); | |
517 | if (EFI_ERROR (Status)) { | |
518 | return Status; | |
519 | } | |
520 | ||
521 | DevicePathSize = GetDevicePathSize (DevicePath); | |
522 | ||
523 | // | |
54cf8780 | 524 | // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL> |
525 | // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 | | |
e52c5a9f | 526 | // |
54cf8780 | 527 | BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16); |
e52c5a9f | 528 | if (*StrBufferLen < BufferSize) { |
529 | *StrBufferLen = BufferSize; | |
530 | return EFI_BUFFER_TOO_SMALL; | |
531 | } | |
532 | ||
533 | *StrBufferLen = BufferSize; | |
534 | ||
535 | StrPtr = ConfigHdr; | |
536 | ||
537 | StrCpy (StrPtr, L"GUID="); | |
538 | StrPtr += 5; | |
539 | BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID)); | |
540 | StrPtr += 32; | |
541 | ||
54cf8780 | 542 | // |
543 | // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044" | |
544 | // | |
e52c5a9f | 545 | StrCpy (StrPtr, L"&NAME="); |
546 | StrPtr += 6; | |
547 | if (Name != NULL) { | |
54cf8780 | 548 | BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16); |
549 | UnicodeToConfigString (StrPtr, &BufferSize, Name); | |
550 | StrPtr += (NameStrLen * 4); | |
e52c5a9f | 551 | } |
552 | ||
553 | StrCpy (StrPtr, L"&PATH="); | |
554 | StrPtr += 6; | |
555 | BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize); | |
556 | ||
557 | return EFI_SUCCESS; | |
558 | } | |
559 | ||
560 | ||
561 | /** | |
562 | Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string. | |
563 | ||
564 | @param String The string to be searched in. | |
565 | @param Offset Offset in BlockName. | |
566 | @param Width Width in BlockName. | |
567 | ||
568 | @retval TRUE Block name found. | |
569 | @retval FALSE Block name not found. | |
570 | ||
571 | **/ | |
572 | BOOLEAN | |
1db1f6ad | 573 | EFIAPI |
e52c5a9f | 574 | FindBlockName ( |
575 | IN OUT CHAR16 *String, | |
576 | UINTN Offset, | |
577 | UINTN Width | |
578 | ) | |
579 | { | |
580 | EFI_STATUS Status; | |
581 | UINTN Data; | |
582 | UINTN BufferSize; | |
583 | UINTN ConvertedStrLen; | |
584 | ||
585 | while ((String = StrStr (String, L"&OFFSET=")) != NULL) { | |
586 | // | |
587 | // Skip '&OFFSET=' | |
588 | // | |
589 | String = String + 8; | |
590 | ||
591 | Data = 0; | |
592 | BufferSize = sizeof (UINTN); | |
d9e5c1ff | 593 | Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen); |
e52c5a9f | 594 | if (EFI_ERROR (Status)) { |
595 | return FALSE; | |
596 | } | |
597 | String = String + ConvertedStrLen; | |
598 | ||
599 | if (Data != Offset) { | |
600 | continue; | |
601 | } | |
602 | ||
603 | if (StrnCmp (String, L"&WIDTH=", 7) != 0) { | |
604 | return FALSE; | |
605 | } | |
606 | String = String + 7; | |
607 | ||
608 | Data = 0; | |
609 | BufferSize = sizeof (UINTN); | |
d9e5c1ff | 610 | Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen); |
e52c5a9f | 611 | if (EFI_ERROR (Status)) { |
612 | return FALSE; | |
613 | } | |
614 | if (Data == Width) { | |
615 | return TRUE; | |
616 | } | |
617 | ||
618 | String = String + ConvertedStrLen; | |
619 | } | |
620 | ||
621 | return FALSE; | |
622 | } | |
623 | ||
624 | ||
625 | /** | |
626 | This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser. | |
627 | ||
628 | @param VariableGuid An optional field to indicate the target variable | |
629 | GUID name to use. | |
630 | @param VariableName An optional field to indicate the target | |
631 | human-readable variable name. | |
632 | @param BufferSize On input: Length in bytes of buffer to hold | |
633 | retrived data. On output: If return | |
634 | EFI_BUFFER_TOO_SMALL, containg length of buffer | |
635 | desired. | |
636 | @param Buffer Buffer to hold retrived data. | |
637 | ||
638 | @retval EFI_SUCCESS Routine success. | |
639 | @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small. | |
640 | ||
641 | **/ | |
642 | EFI_STATUS | |
643 | EFIAPI | |
644 | GetBrowserData ( | |
645 | EFI_GUID *VariableGuid, OPTIONAL | |
646 | CHAR16 *VariableName, OPTIONAL | |
647 | UINTN *BufferSize, | |
648 | UINT8 *Buffer | |
649 | ) | |
650 | { | |
651 | EFI_STATUS Status; | |
1db1f6ad | 652 | CONST CHAR16 *ConfigHdr; |
e52c5a9f | 653 | CHAR16 *ConfigResp; |
654 | CHAR16 *StringPtr; | |
655 | UINTN HeaderLen; | |
656 | UINTN BufferLen; | |
657 | CHAR16 *Progress; | |
658 | EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; | |
659 | EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; | |
660 | ||
661 | // | |
662 | // Locate protocols for use | |
663 | // | |
664 | Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); | |
665 | if (EFI_ERROR (Status)) { | |
666 | return Status; | |
667 | } | |
668 | ||
669 | Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting); | |
670 | if (EFI_ERROR (Status)) { | |
671 | return Status; | |
672 | } | |
673 | ||
674 | // | |
675 | // Retrive formset storage data from Form Browser | |
676 | // | |
677 | ConfigHdr = mFakeConfigHdr; | |
678 | HeaderLen = StrLen (ConfigHdr); | |
679 | ||
680 | BufferLen = 0x4000; | |
681 | ConfigResp = AllocateZeroPool (BufferLen + HeaderLen); | |
682 | ||
683 | StringPtr = ConfigResp + HeaderLen; | |
684 | *StringPtr = L'&'; | |
685 | StringPtr++; | |
686 | ||
687 | Status = FormBrowser2->BrowserCallback ( | |
688 | FormBrowser2, | |
689 | &BufferLen, | |
690 | StringPtr, | |
691 | TRUE, | |
692 | VariableGuid, | |
693 | VariableName | |
694 | ); | |
695 | if (Status == EFI_BUFFER_TOO_SMALL) { | |
1db1f6ad | 696 | FreePool (ConfigResp); |
e52c5a9f | 697 | ConfigResp = AllocateZeroPool (BufferLen + HeaderLen); |
698 | ||
699 | StringPtr = ConfigResp + HeaderLen; | |
700 | *StringPtr = L'&'; | |
701 | StringPtr++; | |
702 | ||
703 | Status = FormBrowser2->BrowserCallback ( | |
704 | FormBrowser2, | |
705 | &BufferLen, | |
706 | StringPtr, | |
707 | TRUE, | |
708 | VariableGuid, | |
709 | VariableName | |
710 | ); | |
711 | } | |
712 | if (EFI_ERROR (Status)) { | |
1db1f6ad | 713 | FreePool (ConfigResp); |
e52c5a9f | 714 | return Status; |
715 | } | |
716 | CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16)); | |
717 | ||
718 | // | |
719 | // Convert <ConfigResp> to buffer data | |
720 | // | |
721 | Status = HiiConfigRouting->ConfigToBlock ( | |
722 | HiiConfigRouting, | |
723 | ConfigResp, | |
724 | Buffer, | |
725 | BufferSize, | |
726 | &Progress | |
727 | ); | |
1db1f6ad | 728 | FreePool (ConfigResp); |
e52c5a9f | 729 | |
730 | return Status; | |
731 | } | |
732 | ||
733 | ||
734 | /** | |
735 | This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser. | |
736 | ||
737 | @param VariableGuid An optional field to indicate the target variable | |
738 | GUID name to use. | |
739 | @param VariableName An optional field to indicate the target | |
740 | human-readable variable name. | |
741 | @param BufferSize Length in bytes of buffer to hold retrived data. | |
742 | @param Buffer Buffer to hold retrived data. | |
743 | @param RequestElement An optional field to specify which part of the | |
744 | buffer data will be send back to Browser. If NULL, | |
745 | the whole buffer of data will be committed to | |
746 | Browser. <RequestElement> ::= | |
747 | &OFFSET=<Number>&WIDTH=<Number>* | |
748 | ||
749 | @retval EFI_SUCCESS Routine success. | |
750 | @retval Other Updating Browser uncommitted data failed. | |
751 | ||
752 | **/ | |
753 | EFI_STATUS | |
754 | EFIAPI | |
755 | SetBrowserData ( | |
756 | EFI_GUID *VariableGuid, OPTIONAL | |
757 | CHAR16 *VariableName, OPTIONAL | |
758 | UINTN BufferSize, | |
759 | UINT8 *Buffer, | |
760 | CHAR16 *RequestElement OPTIONAL | |
761 | ) | |
762 | { | |
763 | EFI_STATUS Status; | |
1db1f6ad | 764 | CONST CHAR16 *ConfigHdr; |
e52c5a9f | 765 | CHAR16 *ConfigResp; |
766 | CHAR16 *StringPtr; | |
767 | UINTN HeaderLen; | |
768 | UINTN BufferLen; | |
769 | CHAR16 *Progress; | |
770 | EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; | |
771 | EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; | |
772 | CHAR16 BlockName[33]; | |
773 | CHAR16 *ConfigRequest; | |
774 | CHAR16 *Request; | |
775 | ||
776 | // | |
777 | // Locate protocols for use | |
778 | // | |
779 | Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); | |
780 | if (EFI_ERROR (Status)) { | |
781 | return Status; | |
782 | } | |
783 | ||
784 | Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting); | |
785 | if (EFI_ERROR (Status)) { | |
786 | return Status; | |
787 | } | |
788 | ||
789 | // | |
790 | // Prepare <ConfigRequest> | |
791 | // | |
792 | ConfigHdr = mFakeConfigHdr; | |
793 | HeaderLen = StrLen (ConfigHdr); | |
794 | ||
795 | if (RequestElement == NULL) { | |
796 | // | |
797 | // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName> | |
798 | // | |
799 | BlockName[0] = L'\0'; | |
800 | StrCpy (BlockName, L"&OFFSET=0&WIDTH="); | |
801 | ||
802 | // | |
803 | // String lenghth of L"&OFFSET=0&WIDTH=" is 16 | |
804 | // | |
805 | StringPtr = BlockName + 16; | |
806 | BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16)); | |
d9e5c1ff | 807 | BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN)); |
e52c5a9f | 808 | |
809 | Request = BlockName; | |
810 | } else { | |
811 | Request = RequestElement; | |
812 | } | |
813 | ||
814 | BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request); | |
815 | ConfigRequest = AllocateZeroPool (BufferLen); | |
816 | ||
817 | CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16)); | |
818 | StringPtr = ConfigRequest + HeaderLen; | |
819 | StrCpy (StringPtr, Request); | |
820 | ||
821 | // | |
822 | // Convert buffer to <ConfigResp> | |
823 | // | |
824 | Status = HiiConfigRouting->BlockToConfig ( | |
825 | HiiConfigRouting, | |
826 | ConfigRequest, | |
827 | Buffer, | |
828 | BufferSize, | |
829 | &ConfigResp, | |
830 | &Progress | |
831 | ); | |
832 | if (EFI_ERROR (Status)) { | |
1db1f6ad | 833 | FreePool (ConfigResp); |
e52c5a9f | 834 | return Status; |
835 | } | |
836 | ||
837 | // | |
838 | // Skip <ConfigHdr> and '&' | |
839 | // | |
840 | StringPtr = ConfigResp + HeaderLen + 1; | |
841 | ||
842 | // | |
843 | // Change uncommitted data in Browser | |
844 | // | |
845 | Status = FormBrowser2->BrowserCallback ( | |
846 | FormBrowser2, | |
847 | &BufferSize, | |
848 | StringPtr, | |
849 | FALSE, | |
850 | NULL, | |
851 | NULL | |
852 | ); | |
1db1f6ad | 853 | FreePool (ConfigResp); |
e52c5a9f | 854 | return Status; |
855 | } |