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