EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

EdkCompatibilityPkg/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrForm.c

Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
00004 This program and the accompanying materials
00005 are licensed and made available under the terms and conditions of the BSD License
00006 which accompanies this distribution.  The full text of the license may be found at
00007 http://opensource.org/licenses/bsd-license.php
00008 
00009 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
00010 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
00011 
00012 Module Name:
00013 
00014   UefiIfrForm.c
00015 
00016 Abstract:
00017 
00018   Common Library Routines to assist handle HII elements.
00019 
00020 --*/
00021 
00022 #include "UefiIfrLibrary.h"
00023 
00024 //
00025 // Fake <ConfigHdr>
00026 //
00027 UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
00028 
00029 EFI_STATUS
00030 GetPackageDataFromPackageList (
00031   IN  EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
00032   IN  UINT32                      PackageIndex,
00033   OUT UINT32                      *BufferLen,
00034   OUT EFI_HII_PACKAGE_HEADER      **Buffer
00035   )
00036 {
00037   UINT32                        Index;
00038   EFI_HII_PACKAGE_HEADER        *Package;
00039   UINT32                        Offset;
00040   UINT32                        PackageListLength;
00041   EFI_HII_PACKAGE_HEADER        PackageHeader = {0, 0};
00042 
00043   ASSERT(HiiPackageList != NULL);
00044 
00045   if ((BufferLen == NULL) || (Buffer == NULL)) {
00046     return EFI_INVALID_PARAMETER;
00047   }
00048 
00049   Package = NULL;
00050   Index   = 0;
00051   Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
00052   EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
00053   while (Offset < PackageListLength) {
00054     Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
00055     EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
00056     if (Index == PackageIndex) {
00057       break;
00058     }
00059     Offset += PackageHeader.Length;
00060     Index++;
00061   }
00062   if (Offset >= PackageListLength) {
00063     //
00064     // no package found in this Package List
00065     //
00066     return EFI_NOT_FOUND;
00067   }
00068 
00069   *BufferLen = PackageHeader.Length;
00070   *Buffer    = Package;
00071   return EFI_SUCCESS;
00072 }
00073 
00074 EFI_STATUS
00075 UpdateFormPackageData (
00076   IN  EFI_GUID               *FormSetGuid,
00077   IN  EFI_FORM_ID            FormId,
00078   IN  EFI_HII_PACKAGE_HEADER *Package,
00079   IN  UINT32                 PackageLength,
00080   IN  UINT16                 Label,
00081   IN  BOOLEAN                Insert,
00082   IN  EFI_HII_UPDATE_DATA    *Data,
00083   OUT UINT8                  **TempBuffer,
00084   OUT UINT32                 *TempBufferSize
00085   )
00086 {
00087   UINT8                     *BufferPos;
00088   EFI_HII_PACKAGE_HEADER    PackageHeader;
00089   UINT32                    Offset;
00090   EFI_IFR_OP_HEADER         *IfrOpHdr;
00091   BOOLEAN                   GetFormSet;
00092   BOOLEAN                   GetForm;
00093   UINT8                     ExtendOpCode;
00094   UINT16                    LabelNumber;
00095   BOOLEAN                   Updated;
00096 
00097   if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {
00098     return EFI_INVALID_PARAMETER;
00099   }
00100 
00101   *TempBufferSize = PackageLength;
00102   if (Data != NULL) {
00103     *TempBufferSize += Data->Offset;
00104   }
00105   *TempBuffer = EfiLibAllocateZeroPool (*TempBufferSize);
00106   if (*TempBuffer == NULL) {
00107     return EFI_OUT_OF_RESOURCES;
00108   }
00109 
00110   EfiCopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));
00111   *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);
00112   BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);
00113 
00114   EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
00115   IfrOpHdr   = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
00116   Offset     = sizeof (EFI_HII_PACKAGE_HEADER);
00117   GetFormSet = (BOOLEAN)((FormSetGuid == NULL) ? TRUE : FALSE);
00118   GetForm    = FALSE;
00119   Updated    = FALSE;
00120 
00121   while (!Updated && Offset < PackageHeader.Length) {
00122     EfiCopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
00123     BufferPos += IfrOpHdr->Length;
00124     *TempBufferSize += IfrOpHdr->Length;
00125 
00126     switch (IfrOpHdr->OpCode) {
00127     case EFI_IFR_FORM_SET_OP :
00128       if (FormSetGuid != NULL) {
00129         if (EfiCompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {
00130           GetFormSet = TRUE;
00131         } else {
00132           GetFormSet = FALSE;
00133         }
00134       }
00135       break;
00136 
00137     case EFI_IFR_FORM_OP:
00138       if (EfiCompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
00139         GetForm = TRUE;
00140       } else {
00141         GetForm = FALSE;
00142       }
00143       break;
00144 
00145     case EFI_IFR_GUID_OP :
00146       if (!GetFormSet || !GetForm) {
00147         //
00148         // Go to the next Op-Code
00149         //
00150         break;
00151       }
00152 
00153       if (!EfiCompareGuid (&((EFI_IFR_GUID *) IfrOpHdr)->Guid, &mIfrVendorGuid)) {
00154         //
00155         // GUID mismatch, skip this op-code
00156         //
00157         break;
00158       }
00159 
00160       ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
00161       EfiCopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
00162       if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) {
00163         //
00164         // Go to the next Op-Code
00165         //
00166         break;
00167       }
00168 
00169       if (Insert) {
00170         //
00171         // Insert data after current Label, skip myself
00172         //
00173         Offset   += IfrOpHdr->Length;
00174         IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
00175       } else {
00176         //
00177         // Replace data between two paired Label, try to find the next Label.
00178         //
00179         while (TRUE) {
00180           Offset   += IfrOpHdr->Length;
00181           //
00182           // Search the next label and Fail if not label found.
00183           //
00184           if (Offset >= PackageHeader.Length) {
00185             goto Fail;
00186           }
00187           IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
00188           if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {
00189             ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
00190             if (EfiCompareGuid (&((EFI_IFR_GUID *) IfrOpHdr)->Guid, &mIfrVendorGuid) && ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) {
00191               break;
00192             }
00193           }
00194         }
00195       }
00196 
00197       //
00198       // Fill in the update data
00199       //
00200       if (Data != NULL) {
00201         EfiCopyMem (BufferPos, Data->Data, Data->Offset);
00202         BufferPos += Data->Offset;
00203         *TempBufferSize += Data->Offset;
00204       }
00205 
00206       //
00207       // Copy the reset data
00208       //
00209       EfiCopyMem (BufferPos, IfrOpHdr, PackageHeader.Length - Offset);
00210       *TempBufferSize += PackageHeader.Length - Offset;
00211 
00212       Updated = TRUE;
00213       break;
00214     default :
00215       break;
00216     }
00217 
00218     //
00219     // Go to the next Op-Code
00220     //
00221     Offset   += IfrOpHdr->Length;
00222     IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
00223   }
00224 
00225   //
00226   // Update the package length.
00227   //
00228   PackageHeader.Length = *TempBufferSize;
00229   EfiCopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
00230 
00231 Fail:
00232   if (!Updated) {
00233     gBS->FreePool (*TempBuffer);
00234     *TempBufferSize = 0;
00235     return EFI_NOT_FOUND;
00236   }
00237 
00238   return EFI_SUCCESS;
00239 }
00240 
00241 EFI_STATUS
00242 IfrLibInitUpdateData (
00243   IN OUT EFI_HII_UPDATE_DATA   *UpdateData,
00244   IN UINT32                    BufferSize
00245   )
00246 /*++
00247 
00248 Routine Description:
00249   This function initialize the data structure for dynamic opcode.
00250 
00251 Arguments:
00252   UpdateData     - The adding data;
00253   BufferSize     - Length of the buffer to fill dynamic opcodes.
00254 
00255 Returns:
00256   EFI_SUCCESS           - Update data is initialized.
00257   EFI_INVALID_PARAMETER - UpdateData is NULL.
00258   EFI_OUT_OF_RESOURCES  - No enough memory to allocate.
00259 
00260 --*/
00261 {
00262   if (UpdateData == NULL) {
00263     return EFI_INVALID_PARAMETER;
00264   }
00265 
00266   UpdateData->BufferSize = BufferSize;
00267   UpdateData->Offset = 0;
00268   UpdateData->Data = EfiLibAllocatePool (BufferSize);
00269 
00270   return (UpdateData->Data != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
00271 }
00272 
00273 EFI_STATUS
00274 IfrLibFreeUpdateData (
00275   IN EFI_HII_UPDATE_DATA       *UpdateData
00276   )
00277 /*++
00278 
00279 Routine Description:
00280   This function free the resource of update data.
00281 
00282 Arguments:
00283   UpdateData     - The adding data;
00284 
00285 Returns:
00286   EFI_SUCCESS           - Resource in UpdateData is released.
00287   EFI_INVALID_PARAMETER - UpdateData is NULL.
00288 
00289 --*/
00290 {
00291   EFI_STATUS  Status;
00292 
00293   if (UpdateData == NULL) {
00294     return EFI_INVALID_PARAMETER;
00295   }
00296 
00297   Status = gBS->FreePool (UpdateData->Data);
00298   UpdateData->Data = NULL;
00299 
00300   return Status;
00301 }
00302 
00303 EFI_STATUS
00304 IfrLibUpdateForm (
00305   IN EFI_HII_HANDLE            Handle,
00306   IN EFI_GUID                  *FormSetGuid, OPTIONAL
00307   IN EFI_FORM_ID               FormId,
00308   IN UINT16                    Label,
00309   IN BOOLEAN                   Insert,
00310   IN EFI_HII_UPDATE_DATA       *Data
00311   )
00312 /*++
00313 
00314 Routine Description:
00315   This function allows the caller to update a form that has
00316   previously been registered with the EFI HII database.
00317 
00318 Arguments:
00319   Handle       - Hii Handle
00320   FormSetGuid  - The formset should be updated.
00321   FormId       - The form should be updated.
00322   Label        - Update information starting immediately after this label in the IFR
00323   Insert       - If TRUE and Data is not NULL, insert data after Label.
00324                  If FALSE, replace opcodes between two labels with Data
00325   Data         - The adding data; If NULL, remove opcodes between two Label.
00326 
00327 Returns:
00328   EFI_SUCCESS  - Update success.
00329   Other        - Update fail.
00330 
00331 --*/
00332 {
00333   EFI_STATUS                   Status;
00334   EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
00335   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
00336   UINT32                       Index;
00337   EFI_HII_PACKAGE_LIST_HEADER  *UpdateBuffer;
00338   UINTN                        BufferSize;
00339   UINT8                        *UpdateBufferPos;
00340   EFI_HII_PACKAGE_HEADER       PackageHeader;
00341   EFI_HII_PACKAGE_HEADER       *Package;
00342   UINT32                       PackageLength;
00343   EFI_HII_PACKAGE_HEADER       *TempBuffer;
00344   UINT32                       TempBufferSize;
00345   BOOLEAN                      Updated;
00346 
00347   if (Data == NULL) {
00348     return EFI_INVALID_PARAMETER;
00349   }
00350 
00351   LocateHiiProtocols ();
00352   HiiDatabase = gIfrLibHiiDatabase;
00353 
00354   //
00355   // Get the orginal package list
00356   //
00357   BufferSize = 0;
00358   HiiPackageList   = NULL;
00359   Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
00360   if (Status == EFI_BUFFER_TOO_SMALL) {
00361     HiiPackageList = EfiLibAllocatePool (BufferSize);
00362     ASSERT (HiiPackageList != NULL);
00363 
00364     Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
00365     if (EFI_ERROR (Status)) {
00366       gBS->FreePool (HiiPackageList);
00367       return Status;
00368     }
00369   }
00370 
00371   //
00372   // Calculate and allocate space for retrieval of IFR data
00373   //
00374   BufferSize += Data->Offset;
00375   UpdateBuffer = EfiLibAllocateZeroPool (BufferSize);
00376   if (UpdateBuffer == NULL) {
00377     return EFI_OUT_OF_RESOURCES;
00378   }
00379 
00380   UpdateBufferPos = (UINT8 *) UpdateBuffer;
00381 
00382   //
00383   // copy the package list header
00384   //
00385   EfiCopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
00386   UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
00387 
00388   Updated = FALSE;
00389   for (Index = 0; ; Index++) {
00390     Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);
00391     if (Status == EFI_SUCCESS) {
00392       EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
00393       if ((PackageHeader.Type == EFI_HII_PACKAGE_FORMS) && !Updated) {
00394         Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);
00395         if (!EFI_ERROR(Status)) {
00396           if (FormSetGuid == NULL) {
00397             Updated = TRUE;
00398           }
00399           EfiCopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);
00400           UpdateBufferPos += TempBufferSize;
00401           gBS->FreePool (TempBuffer);
00402           continue;
00403         }
00404       }
00405 
00406       EfiCopyMem (UpdateBufferPos, Package, PackageLength);
00407       UpdateBufferPos += PackageLength;
00408     } else if (Status == EFI_NOT_FOUND) {
00409       break;
00410     } else {
00411       gBS->FreePool (HiiPackageList);
00412       return Status;
00413     }
00414   }
00415 
00416   //
00417   // Update package list length
00418   //
00419   BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;
00420   EfiCopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));
00421 
00422   gBS->FreePool (HiiPackageList);
00423 
00424   return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);
00425 }
00426 
00427 EFI_STATUS
00428 IfrLibCreatePopUp (
00429   IN  UINTN                       NumberOfLines,
00430   OUT EFI_INPUT_KEY               *KeyValue,
00431   IN  CHAR16                      *String,
00432   ...
00433   )
00434 /*++
00435 
00436 Routine Description:
00437   Draw a dialog and return the selected key.
00438 
00439 Arguments:
00440   NumberOfLines     - The number of lines for the dialog box
00441   KeyValue          - The EFI_KEY value returned if HotKey is TRUE..
00442   String            - Pointer to the first string in the list
00443   ...               - A series of (quantity == NumberOfLines) text strings which
00444                       will be used to construct the dialog box
00445 
00446 Returns:
00447   EFI_SUCCESS           - Displayed dialog and received user interaction
00448   EFI_INVALID_PARAMETER - One of the parameters was invalid.
00449 
00450 --*/
00451 {
00452   UINTN                         Index;
00453   UINTN                         Count;
00454   UINTN                         Start;
00455   UINTN                         End;
00456   UINTN                         Top;
00457   UINTN                         Bottom;
00458   CHAR16                        *StringPtr;
00459   UINTN                         LeftColumn;
00460   UINTN                         RightColumn;
00461   UINTN                         TopRow;
00462   UINTN                         BottomRow;
00463   UINTN                         DimensionsWidth;
00464   UINTN                         DimensionsHeight;
00465   VA_LIST                       Marker;
00466   EFI_INPUT_KEY                 Key;
00467   UINTN                         LargestString;
00468   CHAR16                        *StackString;
00469   EFI_STATUS                    Status;
00470   UINTN                         StringLen;
00471   CHAR16                        *LineBuffer;
00472   CHAR16                        **StringArray;
00473   EFI_EVENT                     TimerEvent;
00474   EFI_EVENT                     WaitList[2];
00475   UINTN                         CurrentAttribute;
00476   EFI_SIMPLE_TEXT_OUT_PROTOCOL  *ConOut;
00477 
00478   if ((KeyValue == NULL) || (String == NULL)) {
00479     return EFI_INVALID_PARAMETER;
00480   }
00481 
00482   TopRow      = 0;
00483   BottomRow   = 0;
00484   LeftColumn  = 0;
00485   RightColumn = 0;
00486 
00487   ConOut = gST->ConOut;
00488   ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);
00489 
00490   DimensionsWidth  = RightColumn - LeftColumn;
00491   DimensionsHeight = BottomRow - TopRow;
00492 
00493   CurrentAttribute = ConOut->Mode->Attribute;
00494 
00495   LineBuffer = EfiLibAllocateZeroPool (DimensionsWidth * sizeof (CHAR16));
00496   ASSERT (LineBuffer != NULL);
00497 
00498   //
00499   // Determine the largest string in the dialog box
00500   // Notice we are starting with 1 since String is the first string
00501   //
00502   StringArray = EfiLibAllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));
00503   LargestString = EfiStrLen (String);
00504   StringArray[0] = String;
00505 
00506   VA_START (Marker, String);
00507   for (Index = 1; Index < NumberOfLines; Index++) {
00508     StackString = VA_ARG (Marker, CHAR16 *);
00509 
00510     if (StackString == NULL) {
00511       return EFI_INVALID_PARAMETER;
00512     }
00513 
00514     StringArray[Index] = StackString;
00515     StringLen = EfiStrLen (StackString);
00516     if (StringLen > LargestString) {
00517       LargestString = StringLen;
00518     }
00519   }
00520 
00521   if ((LargestString + 2) > DimensionsWidth) {
00522     LargestString = DimensionsWidth - 2;
00523   }
00524 
00525   //
00526   // Subtract the PopUp width from total Columns, allow for one space extra on
00527   // each end plus a border.
00528   //
00529   Start     = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;
00530   End       = Start + LargestString + 1;
00531 
00532   Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;
00533   Bottom    = Top + NumberOfLines + 2;
00534 
00535   //
00536   // Disable cursor
00537   //
00538   ConOut->EnableCursor (ConOut, FALSE);
00539   ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
00540 
00541   StringPtr = &LineBuffer[0];
00542   *StringPtr++ = BOXDRAW_DOWN_RIGHT;
00543   for (Index = 0; Index < LargestString; Index++) {
00544     *StringPtr++ = BOXDRAW_HORIZONTAL;
00545   }
00546   *StringPtr++ = BOXDRAW_DOWN_LEFT;
00547   *StringPtr = L'\0';
00548 
00549   ConOut->SetCursorPosition (ConOut, Start, Top);
00550   ConOut->OutputString (ConOut, LineBuffer);
00551 
00552   for (Index = 0; Index < NumberOfLines; Index++) {
00553     StringPtr = &LineBuffer[0];
00554     *StringPtr++ = BOXDRAW_VERTICAL;
00555 
00556     for (Count = 0; Count < LargestString; Count++) {
00557       StringPtr[Count] = L' ';
00558     }
00559 
00560     StringLen = EfiStrLen (StringArray[Index]);
00561     if (StringLen > LargestString) {
00562       StringLen = LargestString;
00563     }
00564     EfiCopyMem (
00565       StringPtr + ((LargestString - StringLen) / 2),
00566       StringArray[Index],
00567       StringLen * sizeof (CHAR16)
00568       );
00569     StringPtr += LargestString;
00570 
00571     *StringPtr++ = BOXDRAW_VERTICAL;
00572     *StringPtr = L'\0';
00573 
00574     ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);
00575     ConOut->OutputString (ConOut, LineBuffer);
00576   }
00577 
00578   StringPtr = &LineBuffer[0];
00579   *StringPtr++ = BOXDRAW_UP_RIGHT;
00580   for (Index = 0; Index < LargestString; Index++) {
00581     *StringPtr++ = BOXDRAW_HORIZONTAL;
00582   }
00583   *StringPtr++ = BOXDRAW_UP_LEFT;
00584   *StringPtr = L'\0';
00585 
00586   ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);
00587   ConOut->OutputString (ConOut, LineBuffer);
00588 
00589   do {
00590     Status = gBS->CreateEvent (EFI_EVENT_TIMER, 0, NULL, NULL, &TimerEvent);
00591 
00592     //
00593     // Set a timer event of 1 second expiration
00594     //
00595     gBS->SetTimer (
00596           TimerEvent,
00597           TimerRelative,
00598           10000000
00599           );
00600 
00601     //
00602     // Wait for the keystroke event or the timer
00603     //
00604     WaitList[0] = gST->ConIn->WaitForKey;
00605     WaitList[1] = TimerEvent;
00606     Status      = gBS->WaitForEvent (2, WaitList, &Index);
00607 
00608     //
00609     // Check for the timer expiration
00610     //
00611     if (!EFI_ERROR (Status) && Index == 1) {
00612       Status = EFI_TIMEOUT;
00613     }
00614 
00615     gBS->CloseEvent (TimerEvent);
00616   } while (Status == EFI_TIMEOUT);
00617 
00618   Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
00619   EfiCopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
00620 
00621   ConOut->SetAttribute (ConOut, CurrentAttribute);
00622   ConOut->EnableCursor (ConOut, TRUE);
00623 
00624   return Status;
00625 }
00626 
00627 EFI_STATUS
00628 ExtractDefault(
00629   IN VOID                         *Buffer,
00630   IN UINTN                        *BufferSize,
00631   UINTN                           Number,
00632   ...
00633   )
00634 /*++
00635 
00636   Routine Description:
00637 
00638     Configure the buffer accrording to ConfigBody strings.
00639 
00640   Arguments:
00641     DefaultId             - the ID of default.
00642     Buffer                - the start address of buffer.
00643     BufferSize            - the size of buffer.
00644     Number                - the number of the strings.
00645 
00646   Returns:
00647     EFI_BUFFER_TOO_SMALL  - the BufferSize is too small to operate.
00648     EFI_INVALID_PARAMETER - Buffer is NULL or BufferSize is 0.
00649     EFI_SUCCESS           - Operation successful.
00650 
00651 --*/
00652 {
00653   VA_LIST                         Args;
00654   UINTN                           Index;
00655   UINT32                          TotalLen;
00656   UINT8                           *BufCfgArray;
00657   UINT8                           *BufferPos;
00658   UINT16                          Offset;
00659   UINT16                          Width;
00660   UINT8                           *Value;
00661 
00662   if ((Buffer == NULL) || (BufferSize == NULL)) {
00663     return EFI_INVALID_PARAMETER;
00664   }
00665 
00666   Offset = 0;
00667   Width  = 0;
00668   Value  = NULL;
00669 
00670   VA_START (Args, Number);
00671   for (Index = 0; Index < Number; Index++) {
00672     BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);
00673     EfiCopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));
00674     BufferPos = BufCfgArray + sizeof (UINT32);
00675 
00676     while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {
00677       EfiCopyMem (&Offset, BufferPos, sizeof (UINT16));
00678       BufferPos += sizeof (UINT16);
00679       EfiCopyMem (&Width, BufferPos, sizeof (UINT16));
00680       BufferPos += sizeof (UINT16);
00681       Value = BufferPos;
00682       BufferPos += Width;
00683 
00684       if ((UINTN)(Offset + Width) > *BufferSize) {
00685         return EFI_BUFFER_TOO_SMALL;
00686       }
00687 
00688       EfiCopyMem ((UINT8 *)Buffer + Offset, Value, Width);
00689     }
00690   }
00691   VA_END (Args);
00692 
00693   *BufferSize = (UINTN)Offset;
00694 
00695   return EFI_SUCCESS;
00696 }
00697 
00698 EFI_STATUS
00699 ExtractBlockName (
00700   IN UINT8                        *Buffer,
00701   OUT CHAR16                      **BlockName
00702   )
00703 /*++
00704 
00705   Routine Description:
00706 
00707     Extract block name from the array generated by VFR compiler. The name of
00708   this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName".
00709   Format of this array is:
00710      Array length | 4-bytes
00711        Offset     | 2-bytes
00712        Width      | 2-bytes
00713        Offset     | 2-bytes
00714        Width      | 2-bytes
00715        ... ...
00716 
00717   Arguments:
00718     Buffer                - Array generated by VFR compiler.
00719     BlockName             - The returned <BlockName>
00720 
00721   Returns:
00722     EFI_OUT_OF_RESOURCES  - Run out of memory resource.
00723     EFI_INVALID_PARAMETER - Buffer is NULL or BlockName is NULL.
00724     EFI_SUCCESS           - Operation successful.
00725 
00726 --*/
00727 {
00728   UINTN       Index;
00729   UINT32      Length;
00730   UINT32      BlockNameNumber;
00731   UINTN       HexStringBufferLen;
00732   CHAR16      *StringPtr;
00733 
00734   if ((Buffer == NULL) || (BlockName == NULL)) {
00735     return EFI_INVALID_PARAMETER;
00736   }
00737 
00738   //
00739   // Calculate number of Offset/Width pair
00740   //
00741   EfiCopyMem (&Length, Buffer, sizeof (UINT32));
00742   BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2);
00743 
00744   //
00745   // <BlockName> ::= &OFFSET=1234&WIDTH=1234
00746   //                 |   8  | 4 |  7   | 4 |
00747   //
00748   StringPtr = EfiLibAllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16));
00749   *BlockName = StringPtr;
00750   if (StringPtr == NULL) {
00751     return EFI_OUT_OF_RESOURCES;
00752   }
00753 
00754   Buffer += sizeof (UINT32);
00755   for (Index = 0; Index < BlockNameNumber; Index++) {
00756     EfiStrCpy (StringPtr, L"&OFFSET=");
00757     StringPtr += 8;
00758 
00759     HexStringBufferLen = 5;
00760     BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
00761     Buffer += sizeof (UINT16);
00762     StringPtr += 4;
00763 
00764     EfiStrCpy (StringPtr, L"&WIDTH=");
00765     StringPtr += 7;
00766 
00767     HexStringBufferLen = 5;
00768     BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
00769     Buffer += sizeof (UINT16);
00770     StringPtr += 4;
00771   }
00772 
00773   return EFI_SUCCESS;
00774 }
00775 
00776 EFI_STATUS
00777 ExtractBlockConfig (
00778   IN UINT8                        *Buffer,
00779   OUT CHAR16                      **BlockConfig
00780   )
00781 /*++
00782 
00783   Routine Description:
00784 
00785     Extract block config from the array generated by VFR compiler. The name of
00786   this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000".
00787 
00788   Arguments:
00789     Buffer                - Array generated by VFR compiler.
00790     BlockConfig           - The returned <BlockConfig>
00791 
00792   Returns:
00793     EFI_OUT_OF_RESOURCES  - Run out of memory resource.
00794     EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL.
00795     EFI_SUCCESS           - Operation successful.
00796 
00797 --*/
00798 {
00799   UINT32      Length;
00800   UINT16      Width;
00801   UINTN       HexStringBufferLen;
00802   CHAR16      *StringPtr;
00803   UINT8       *BufferEnd;
00804   CHAR16      *StringEnd;
00805   EFI_STATUS  Status;
00806 
00807   if ((Buffer == NULL) || (BlockConfig == NULL)) {
00808     return EFI_INVALID_PARAMETER;
00809   }
00810 
00811   //
00812   // Calculate length of AltResp string
00813   // Format of Default value array is:
00814   //  Array length | 4-bytes
00815   //        Offset | 2-bytes
00816   //        Width  | 2-bytes
00817   //        Value  | Variable length
00818   //        Offset | 2-bytes
00819   //        Width  | 2-bytes
00820   //        Value  | Variable length
00821   //        ... ...
00822   // When value is 1 byte in length, overhead of AltResp string will be maximum,
00823   //  BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+
00824   //                   |   8   | 4  |  7   | 4 |  7  |2|
00825   // so the maximum length of BlockConfig could be calculated as:
00826   // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7
00827   //
00828   EfiCopyMem (&Length, Buffer, sizeof (UINT32));
00829   BufferEnd = Buffer + Length;
00830   StringPtr = EfiLibAllocatePool (Length * 7 * sizeof (CHAR16));
00831   *BlockConfig = StringPtr;
00832   if (StringPtr == NULL) {
00833       return EFI_OUT_OF_RESOURCES;
00834   }
00835   StringEnd = StringPtr + (Length * 7);
00836 
00837   Buffer += sizeof (UINT32);
00838   while (Buffer < BufferEnd) {
00839     EfiStrCpy (StringPtr, L"&OFFSET=");
00840     StringPtr += 8;
00841 
00842     HexStringBufferLen = 5;
00843     BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
00844     Buffer += sizeof (UINT16);
00845     StringPtr += 4;
00846 
00847     EfiStrCpy (StringPtr, L"&WIDTH=");
00848     StringPtr += 7;
00849 
00850     HexStringBufferLen = 5;
00851     BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));
00852     EfiCopyMem (&Width, Buffer, sizeof (UINT16));
00853     Buffer += sizeof (UINT16);
00854     StringPtr += 4;
00855 
00856     EfiStrCpy (StringPtr, L"&VALUE=");
00857     StringPtr += 7;
00858 
00859     HexStringBufferLen = StringEnd - StringPtr;
00860     Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width);
00861     if (EFI_ERROR (Status)) {
00862       return Status;
00863     }
00864     Buffer += Width;
00865     StringPtr += (Width * 2);
00866   }
00867 
00868   return EFI_SUCCESS;
00869 }
00870 
00871 EFI_STATUS
00872 ConstructConfigAltResp (
00873   IN  EFI_STRING                  ConfigRequest,  OPTIONAL
00874   OUT EFI_STRING                  *Progress,
00875   OUT EFI_STRING                  *ConfigAltResp,
00876   IN  EFI_GUID                    *Guid,
00877   IN  CHAR16                      *Name,
00878   IN  EFI_HANDLE                  *DriverHandle,
00879   IN  VOID                        *BufferStorage,
00880   IN  UINTN                       BufferStorageSize,
00881   IN  VOID                        *BlockNameArray, OPTIONAL
00882   IN  UINTN                       NumberAltCfg,
00883   ...
00884 //IN  UINT16                      AltCfgId,
00885 //IN  VOID                        *DefaultValueArray,
00886   )
00887 /*++
00888 
00889   Routine Description:
00890 
00891   Construct <ConfigAltResp> for a buffer storage.
00892 
00893   Arguments:
00894     ConfigRequest         - The Config request string. If set to NULL, all the
00895                             configurable elements will be extracted from BlockNameArray.
00896     ConfigAltResp         - The returned <ConfigAltResp>.
00897     Progress              - On return, points to a character in the Request.
00898     Guid                  - GUID of the buffer storage.
00899     Name                  - Name of the buffer storage.
00900     DriverHandle          - The DriverHandle which is used to invoke HiiDatabase
00901                             protocol interface NewPackageList().
00902     BufferStorage         - Content of the buffer storage.
00903     BufferStorageSize     - Length in bytes of the buffer storage.
00904     BlockNameArray        - Array generated by VFR compiler.
00905     NumberAltCfg          - Number of Default value array generated by VFR compiler.
00906                             The sequential input parameters will be number of
00907                             AltCfgId and DefaultValueArray pairs. When set to 0,
00908                             there will be no <AltResp>.
00909 
00910   Returns:
00911     EFI_OUT_OF_RESOURCES  - Run out of memory resource.
00912     EFI_INVALID_PARAMETER - ConfigAltResp is NULL.
00913     EFI_SUCCESS           - Operation successful.
00914 
00915 --*/
00916 {
00917   EFI_STATUS                      Status;
00918   CHAR16                          *ConfigHdr;
00919   CHAR16                          *BlockName;
00920   CHAR16                          *DescHdr;
00921   CHAR16                          *StringPtr;
00922   CHAR16                          **AltCfg;
00923   UINT16                          AltCfgId;
00924   VOID                            *DefaultValueArray;
00925   UINTN                           StrBufferLen;
00926   EFI_STRING                      ConfigResp;
00927   EFI_STRING                      TempStr;
00928   VA_LIST                         Args;
00929   UINTN                           AltRespLen;
00930   UINTN                           Index;
00931   BOOLEAN                         NeedFreeConfigRequest;
00932   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
00933 
00934   if (ConfigAltResp == NULL) {
00935     return EFI_INVALID_PARAMETER;
00936   }
00937 
00938   //
00939   // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
00940   //
00941   ConfigHdr = NULL;
00942   StrBufferLen = 0;
00943   Status = ConstructConfigHdr (
00944              ConfigHdr,
00945              &StrBufferLen,
00946              Guid,
00947              Name,
00948              DriverHandle
00949              );
00950   if (Status == EFI_BUFFER_TOO_SMALL) {
00951     ConfigHdr = EfiLibAllocateZeroPool (StrBufferLen);
00952     Status = ConstructConfigHdr (
00953                ConfigHdr,
00954                &StrBufferLen,
00955                Guid,
00956                Name,
00957                DriverHandle
00958                );
00959   }
00960 
00961   if (EFI_ERROR (Status) || (ConfigHdr == NULL)) {
00962     return Status;
00963   }
00964 
00965   //
00966   // Construct <ConfigResp>
00967   //
00968   NeedFreeConfigRequest = FALSE;
00969   if (ConfigRequest == NULL) {
00970     //
00971     // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray
00972     //
00973     Status = ExtractBlockName (BlockNameArray, &BlockName);
00974     if (EFI_ERROR (Status)) {
00975       return Status;
00976     }
00977 
00978     StrBufferLen = EfiStrSize (ConfigHdr);
00979     StrBufferLen = StrBufferLen + EfiStrSize (BlockName) - sizeof (CHAR16);
00980     ConfigRequest = EfiLibAllocateZeroPool (StrBufferLen);
00981     EfiStrCpy (ConfigRequest, ConfigHdr);
00982     EfiStrCat (ConfigRequest, BlockName);
00983     NeedFreeConfigRequest = TRUE;
00984   }
00985 
00986   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
00987   if (EFI_ERROR (Status)) {
00988     return Status;
00989   }
00990 
00991   Status = HiiConfigRouting->BlockToConfig (
00992                                HiiConfigRouting,
00993                                ConfigRequest,
00994                                BufferStorage,
00995                                BufferStorageSize,
00996                                &ConfigResp,
00997                                (Progress == NULL) ? &TempStr : Progress
00998                                );
00999   if (EFI_ERROR (Status)) {
01000     return Status;
01001   }
01002 
01003   //
01004   // Construct <AltResp>
01005   //
01006   DescHdr = EfiLibAllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));
01007   StringPtr = DescHdr;
01008   AltCfg = EfiLibAllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));
01009   AltRespLen = 0;
01010   VA_START (Args, NumberAltCfg);
01011   for (Index = 0; Index < NumberAltCfg; Index++) {
01012     AltCfgId = (UINT16) VA_ARG (Args, UINT16);
01013     DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);
01014 
01015     //
01016     // '&' <ConfigHdr>
01017     //
01018     AltRespLen += (EfiStrLen (ConfigHdr) + 1);
01019 
01020     StringPtr = DescHdr + Index * 16;
01021     EfiStrCpy (StringPtr, L"&ALTCFG=");
01022     AltRespLen += (8 + sizeof (UINT16) * 2);
01023 
01024     StrBufferLen = 5;
01025     BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));
01026     Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);
01027     if (EFI_ERROR (Status)) {
01028       return Status;
01029     }
01030     AltRespLen += EfiStrLen (AltCfg[Index]);
01031   }
01032   VA_END (Args);
01033 
01034   //
01035   // Generate the final <ConfigAltResp>
01036   //
01037   StrBufferLen = (EfiStrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16);
01038   TempStr = EfiLibAllocateZeroPool (StrBufferLen);
01039   *ConfigAltResp = TempStr;
01040   if (TempStr == NULL) {
01041     return EFI_OUT_OF_RESOURCES;
01042   }
01043 
01044   //
01045   // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*
01046   //
01047   EfiStrCpy (TempStr, ConfigResp);
01048   for (Index = 0; Index < NumberAltCfg; Index++) {
01049     EfiStrCat (TempStr, L"&");
01050     EfiStrCat (TempStr, ConfigHdr);
01051     EfiStrCat (TempStr, DescHdr + Index * 16);
01052     EfiStrCat (TempStr, AltCfg[Index]);
01053 
01054     gBS->FreePool (AltCfg[Index]);
01055   }
01056 
01057   if (NeedFreeConfigRequest) {
01058     gBS->FreePool (ConfigRequest);
01059   }
01060   gBS->FreePool (ConfigHdr);
01061   gBS->FreePool (ConfigResp);
01062   gBS->FreePool (DescHdr);
01063   gBS->FreePool (AltCfg);
01064 
01065   return EFI_SUCCESS;
01066 }
01067 
01068 VOID
01069 SwapBuffer (
01070   IN OUT UINT8     *Buffer,
01071   IN UINTN         BufferSize
01072   )
01073 /*++
01074 
01075 Routine Description:
01076   Swap bytes in the buffer.
01077 
01078 Arguments:
01079   Buffer     -  Binary buffer.
01080   BufferSize -  Size of the buffer in bytes.
01081 
01082 Returns:
01083   None.
01084 
01085 --*/
01086 {
01087   UINTN  Index;
01088   UINT8  Temp;
01089   UINTN  SwapCount;
01090 
01091   SwapCount = BufferSize / 2;
01092   for (Index = 0; Index < SwapCount; Index++) {
01093     Temp = Buffer[Index];
01094     Buffer[Index] = Buffer[BufferSize - 1 - Index];
01095     Buffer[BufferSize - 1 - Index] = Temp;
01096   }
01097 }
01098 
01099 VOID
01100 ToLower (
01101   IN OUT CHAR16    *Str
01102   )
01103 /*++
01104 
01105 Routine Description:
01106   Converts the unicode character of the string from uppercase to lowercase.
01107 
01108 Arguments:
01109   Str        -  String to be converted
01110 
01111 Returns:
01112 
01113 --*/
01114 {
01115   CHAR16      *Ptr;
01116 
01117   for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
01118     if (*Ptr >= L'A' && *Ptr <= L'Z') {
01119       *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
01120     }
01121   }
01122 }
01123 
01124 EFI_STATUS
01125 BufferToHexString (
01126   IN OUT CHAR16    *Str,
01127   IN UINT8         *Buffer,
01128   IN UINTN         BufferSize
01129   )
01130 /*++
01131 
01132 Routine Description:
01133   Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
01134 
01135 Arguments:
01136   Str        -  String for output
01137   Buffer     -  Binary buffer.
01138   BufferSize -  Size of the buffer in bytes.
01139 
01140 Returns:
01141   EFI_SUCCESS  -  The function completed successfully.
01142 
01143 --*/
01144 {
01145   EFI_STATUS  Status;
01146   UINT8       *NewBuffer;
01147   UINTN       StrBufferLen;
01148 
01149   NewBuffer = EfiLibAllocateCopyPool (BufferSize, Buffer);
01150   SwapBuffer (NewBuffer, BufferSize);
01151 
01152   StrBufferLen = BufferSize * 2 + 1;
01153   Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
01154 
01155   gBS->FreePool (NewBuffer);
01156   //
01157   // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
01158   //
01159   ToLower (Str);
01160 
01161   return Status;
01162 }
01163 
01164 EFI_STATUS
01165 HexStringToBuffer (
01166   IN OUT UINT8         *Buffer,
01167   IN OUT UINTN         *BufferSize,
01168   IN CHAR16            *Str
01169   )
01170 /*++
01171 
01172 Routine Description:
01173   Converts Hex String to binary buffer in reversed byte order from HexStringToBuf().
01174 
01175 Arguments:
01176     Buffer     - Pointer to buffer that receives the data.
01177     BufferSize - Length in bytes of the buffer to hold converted data.
01178                  If routine return with EFI_SUCCESS, containing length of converted data.
01179                  If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
01180     Str        - String to be converted from.
01181 
01182 Returns:
01183   EFI_SUCCESS    -  The function completed successfully.
01184 
01185 --*/
01186 {
01187   EFI_STATUS  Status;
01188   UINTN       ConvertedStrLen;
01189 
01190   ConvertedStrLen = 0;
01191   Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
01192   if (!EFI_ERROR (Status)) {
01193     SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2);
01194   }
01195 
01196   return Status;
01197 }
01198 
01199 EFI_STATUS
01200 ConfigStringToUnicode (
01201   IN OUT CHAR16                *UnicodeString,
01202   IN OUT UINTN                 *StrBufferLen,
01203   IN CHAR16                    *ConfigString
01204   )
01205 /*++
01206 
01207 Routine Description:
01208   Convert binary representation Config string (e.g. "0041004200430044") to the
01209   original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e.
01210   "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
01211 
01212 Arguments:
01213   UnicodeString - Original Unicode string.
01214   StrBufferLen  - On input: Length in bytes of buffer to hold the Unicode string.
01215                   Includes tailing '\0' character.
01216                   On output:
01217                     If return EFI_SUCCESS, containing length of Unicode string buffer.
01218                     If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
01219   ConfigString  - Binary representation of Unicode String, <string> := (<HexCh>4)+
01220 
01221 Returns:
01222   EFI_SUCCESS          - Routine success.
01223   EFI_BUFFER_TOO_SMALL - The string buffer is too small.
01224 
01225 --*/
01226 {
01227   UINTN       Index;
01228   UINTN       Len;
01229   UINTN       BufferSize;
01230   CHAR16      BackupChar;
01231 
01232   Len = EfiStrLen (ConfigString) / 4;
01233   BufferSize = (Len + 1) * sizeof (CHAR16);
01234 
01235   if (*StrBufferLen < BufferSize) {
01236     *StrBufferLen = BufferSize;
01237     return EFI_BUFFER_TOO_SMALL;
01238   }
01239 
01240   *StrBufferLen = BufferSize;
01241 
01242   for (Index = 0; Index < Len; Index++) {
01243     BackupChar = ConfigString[4];
01244     ConfigString[4] = L'\0';
01245 
01246     HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL);
01247 
01248     ConfigString[4] = BackupChar;
01249 
01250     ConfigString += 4;
01251     UnicodeString += 1;
01252   }
01253 
01254   //
01255   // Add tailing '\0' character
01256   //
01257   *UnicodeString = L'\0';
01258 
01259   return EFI_SUCCESS;
01260 }
01261 
01262 EFI_STATUS
01263 UnicodeToConfigString (
01264   IN OUT CHAR16                *ConfigString,
01265   IN OUT UINTN                 *StrBufferLen,
01266   IN CHAR16                    *UnicodeString
01267   )
01268 /*++
01269 
01270 Routine Description:
01271   Convert Unicode string to binary representation Config string, e.g.
01272   "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
01273   "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
01274 
01275 Arguments:
01276   ConfigString  - Binary representation of Unicode String, <string> := (<HexCh>4)+
01277   StrBufferLen  - On input: Length in bytes of buffer to hold the Unicode string.
01278                   Includes tailing '\0' character.
01279                   On output:
01280                     If return EFI_SUCCESS, containing length of Unicode string buffer.
01281                     If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
01282   UnicodeString - Original Unicode string.
01283 
01284 Returns:
01285   EFI_SUCCESS          - Routine success.
01286   EFI_BUFFER_TOO_SMALL - The string buffer is too small.
01287 
01288 --*/
01289 {
01290   UINTN       Index;
01291   UINTN       Len;
01292   UINTN       BufferSize;
01293   CHAR16      *String;
01294 
01295   Len = EfiStrLen (UnicodeString);
01296   BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
01297 
01298   if (*StrBufferLen < BufferSize) {
01299     *StrBufferLen = BufferSize;
01300     return EFI_BUFFER_TOO_SMALL;
01301   }
01302 
01303   *StrBufferLen = BufferSize;
01304   String        = ConfigString;
01305 
01306   for (Index = 0; Index < Len; Index++) {
01307     BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
01308 
01309     ConfigString += 4;
01310     UnicodeString += 1;
01311   }
01312 
01313   //
01314   // Add tailing '\0' character
01315   //
01316   *ConfigString = L'\0';
01317 
01318   //
01319   // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
01320   //
01321   ToLower (String);
01322   return EFI_SUCCESS;
01323 }
01324 
01325 EFI_STATUS
01326 ConstructConfigHdr (
01327   IN OUT CHAR16                *ConfigHdr,
01328   IN OUT UINTN                 *StrBufferLen,
01329   IN EFI_GUID                  *Guid,
01330   IN CHAR16                    *Name, OPTIONAL
01331   IN EFI_HANDLE                *DriverHandle
01332   )
01333 /*++
01334 
01335 Routine Description:
01336   Construct <ConfigHdr> using routing information GUID/NAME/PATH.
01337 
01338 Arguments:
01339   ConfigHdr    - Pointer to the ConfigHdr string.
01340   StrBufferLen - On input: Length in bytes of buffer to hold the ConfigHdr string.
01341                  Includes tailing '\0' character.
01342                  On output:
01343                     If return EFI_SUCCESS, containing length of ConfigHdr string buffer.
01344                     If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
01345   Guid         - Routing information: GUID.
01346   Name         - Routing information: NAME.
01347   DriverHandle - Driver handle which contains the routing information: PATH.
01348 
01349 Returns:
01350   EFI_SUCCESS          - Routine success.
01351   EFI_BUFFER_TOO_SMALL - The ConfigHdr string buffer is too small.
01352 
01353 --*/
01354 {
01355   EFI_STATUS                Status;
01356   UINTN                     NameStrLen;
01357   UINTN                     DevicePathSize;
01358   UINTN                     BufferSize;
01359   CHAR16                    *StrPtr;
01360   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
01361 
01362   if (Name == NULL) {
01363     //
01364     // There will be no "NAME" in <ConfigHdr> for  Name/Value storage
01365     //
01366     NameStrLen = 0;
01367   } else {
01368     //
01369     // For buffer storage
01370     //
01371     NameStrLen = EfiStrLen (Name);
01372   }
01373 
01374   //
01375   // Retrieve DevicePath Protocol associated with this HiiPackageList
01376   //
01377   Status = gBS->HandleProtocol (
01378                   DriverHandle,
01379                   &gEfiDevicePathProtocolGuid,
01380                   (VOID **) &DevicePath
01381                   );
01382   if (EFI_ERROR (Status)) {
01383     return Status;
01384   }
01385 
01386   DevicePathSize = EfiDevicePathSize (DevicePath);
01387 
01388   //
01389   // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
01390   // | 5  |   32   |  6  |  NameStrLen*4 |  6  |    DevicePathStrLen    | 1 |
01391   //
01392   BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
01393   if (*StrBufferLen < BufferSize) {
01394     *StrBufferLen = BufferSize;
01395     return EFI_BUFFER_TOO_SMALL;
01396   }
01397 
01398   if (ConfigHdr == NULL) {
01399     return EFI_INVALID_PARAMETER;
01400   }
01401 
01402   *StrBufferLen = BufferSize;
01403 
01404   StrPtr = ConfigHdr;
01405 
01406   EfiStrCpy (StrPtr, L"GUID=");
01407   StrPtr += 5;
01408   BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
01409   StrPtr += 32;
01410 
01411   //
01412   // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
01413   //
01414   EfiStrCpy (StrPtr, L"&NAME=");
01415   StrPtr += 6;
01416   if (Name != NULL) {
01417     BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
01418     UnicodeToConfigString (StrPtr, &BufferSize, Name);
01419     StrPtr += (NameStrLen * 4);
01420   }
01421 
01422   EfiStrCpy (StrPtr, L"&PATH=");
01423   StrPtr += 6;
01424   BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
01425 
01426   return EFI_SUCCESS;
01427 }
01428 
01429 BOOLEAN
01430 IsConfigHdrMatch (
01431   IN EFI_STRING                ConfigString,
01432   IN EFI_GUID                  *StorageGuid, OPTIONAL
01433   IN CHAR16                    *StorageName  OPTIONAL
01434   )
01435 /*++
01436 
01437 Routine Description:
01438   Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.
01439 
01440 Arguments:
01441   ConfigString - Either <ConfigRequest> or <ConfigResp>.
01442   StorageGuid  - GUID of the storage.
01443   StorageName  - Name of the stoarge.
01444 
01445 Returns:
01446   TRUE         - Routing information is correct in ConfigString.
01447   FALSE        - Routing information is incorrect in ConfigString.
01448 
01449 --*/
01450 {
01451   EFI_STATUS  Status;
01452   BOOLEAN     Match;
01453   EFI_GUID    Guid;
01454   CHAR16      *Name;
01455   CHAR16      *StrPtr;
01456   UINTN       BufferSize;
01457 
01458   //
01459   // <ConfigHdr> ::=
01460   // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
01461   // | 5  |   32   |  6  |  NameStrLen*4 |  6  |    DevicePathStrLen    | 1 |
01462   //
01463   if (EfiStrLen (ConfigString) <= (5 + 32 + 6)) {
01464     return FALSE;
01465   }
01466 
01467   //
01468   // Compare GUID
01469   //
01470   if (StorageGuid != NULL) {
01471 
01472     StrPtr = ConfigString + 5 + 32;
01473     if (*StrPtr != L'&') {
01474       return FALSE;
01475     }
01476     *StrPtr = L'\0';
01477 
01478     BufferSize = sizeof (EFI_GUID);
01479     Status = HexStringToBuffer (
01480                (UINT8 *) &Guid,
01481                &BufferSize,
01482                ConfigString + 5
01483                );
01484     *StrPtr = L'&';
01485 
01486     if (EFI_ERROR (Status)) {
01487       return FALSE;
01488     }
01489 
01490     if (!EfiCompareGuid (&Guid, StorageGuid)) {
01491       return FALSE;
01492     }
01493   }
01494 
01495   //
01496   // Compare Name
01497   //
01498   Match = TRUE;
01499   if (StorageName != NULL) {
01500     StrPtr = ConfigString + 5 + 32 + 6;
01501     while (*StrPtr != L'\0' && *StrPtr != L'&') {
01502       StrPtr++;
01503     }
01504     if (*StrPtr != L'&') {
01505       return FALSE;
01506     }
01507 
01508     *StrPtr = L'\0';
01509     BufferSize = (EfiStrLen (ConfigString + 5 + 32 + 6) + 1) * sizeof (CHAR16);
01510     Name = EfiLibAllocatePool (BufferSize);
01511     ASSERT (Name != NULL);
01512     Status = ConfigStringToUnicode (
01513                Name,
01514                &BufferSize,
01515                ConfigString + 5 + 32 + 6
01516                );
01517     *StrPtr = L'&';
01518 
01519     if (EFI_ERROR (Status) || (EfiStrCmp (Name, StorageName) != 0)) {
01520       Match = FALSE;
01521     }
01522     gBS->FreePool (Name);
01523   }
01524 
01525   return Match;
01526 }
01527 
01528 BOOLEAN
01529 FindBlockName (
01530   IN OUT CHAR16                *String,
01531   UINTN                        Offset,
01532   UINTN                        Width
01533   )
01534 /*++
01535 
01536 Routine Description:
01537   Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
01538 
01539 Arguments:
01540   String       - The string to be searched in.
01541   Offset       - Offset in BlockName.
01542   Width        - Width in BlockName.
01543 
01544 Returns:
01545   TRUE         - Block name found.
01546   FALSE        - Block name not found.
01547 
01548 --*/
01549 {
01550   EFI_STATUS  Status;
01551   UINTN       Data;
01552   UINTN       BufferSize;
01553   UINTN       ConvertedStrLen;
01554 
01555   while ((String = EfiStrStr (String, L"&OFFSET=")) != NULL) {
01556     //
01557     // Skip '&OFFSET='
01558     //
01559     String = String + 8;
01560 
01561     Data = 0;
01562     BufferSize = sizeof (UINTN);
01563     Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
01564     if (EFI_ERROR (Status)) {
01565       return FALSE;
01566     }
01567     String = String + ConvertedStrLen;
01568 
01569     if (Data != Offset) {
01570       continue;
01571     }
01572 
01573     if (EfiStrnCmp (String, L"&WIDTH=", 7) != 0) {
01574       return FALSE;
01575     }
01576     String = String + 7;
01577 
01578     Data = 0;
01579     BufferSize = sizeof (UINTN);
01580     Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
01581     if (EFI_ERROR (Status)) {
01582       return FALSE;
01583     }
01584     if (Data == Width) {
01585       return TRUE;
01586     }
01587 
01588     String = String + ConvertedStrLen;
01589   }
01590 
01591   return FALSE;
01592 }
01593 
01594 EFI_STATUS
01595 GetBrowserData (
01596   EFI_GUID                   *VariableGuid, OPTIONAL
01597   CHAR16                     *VariableName, OPTIONAL
01598   UINTN                      *BufferSize,
01599   UINT8                      *Buffer
01600   )
01601 /*++
01602 
01603 Routine Description:
01604   This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
01605 
01606 Arguments:
01607   VariableGuid  - An optional field to indicate the target variable GUID name to use.
01608   VariableName  - An optional field to indicate the target human-readable variable name.
01609   BufferSize    - On input: Length in bytes of buffer to hold retrived data.
01610                   On output:
01611                     If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
01612   Buffer        - Buffer to hold retrived data.
01613 
01614 Returns:
01615   EFI_SUCCESS          - Routine success.
01616   EFI_BUFFER_TOO_SMALL - The intput buffer is too small.
01617 
01618 --*/
01619 {
01620   EFI_STATUS                      Status;
01621   CHAR16                          *ConfigHdr;
01622   CHAR16                          *ConfigResp;
01623   CHAR16                          *StringPtr;
01624   UINTN                           HeaderLen;
01625   UINTN                           BufferLen;
01626   CHAR16                          *Progress;
01627   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
01628   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
01629 
01630   //
01631   // Locate protocols for use
01632   //
01633   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
01634   if (EFI_ERROR (Status)) {
01635     return Status;
01636   }
01637 
01638   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
01639   if (EFI_ERROR (Status)) {
01640     return Status;
01641   }
01642 
01643   //
01644   // Retrive formset storage data from Form Browser
01645   //
01646   ConfigHdr = mFakeConfigHdr;
01647   HeaderLen = EfiStrLen (ConfigHdr);
01648 
01649   BufferLen = 0x4000;
01650   ConfigResp = EfiLibAllocateZeroPool (BufferLen + (HeaderLen + 1) * sizeof (CHAR16));
01651 
01652   StringPtr = ConfigResp + HeaderLen;
01653   *StringPtr = L'&';
01654   StringPtr++;
01655 
01656   Status = FormBrowser2->BrowserCallback (
01657                            FormBrowser2,
01658                            &BufferLen,
01659                            StringPtr,
01660                            TRUE,
01661                            VariableGuid,
01662                            VariableName
01663                            );
01664   if (Status == EFI_BUFFER_TOO_SMALL) {
01665     gBS->FreePool (ConfigResp);
01666     ConfigResp = EfiLibAllocateZeroPool (BufferLen + (HeaderLen + 1) * sizeof (CHAR16));
01667 
01668     StringPtr = ConfigResp + HeaderLen;
01669     *StringPtr = L'&';
01670     StringPtr++;
01671 
01672     Status = FormBrowser2->BrowserCallback (
01673                              FormBrowser2,
01674                              &BufferLen,
01675                              StringPtr,
01676                              TRUE,
01677                              VariableGuid,
01678                              VariableName
01679                              );
01680   }
01681   if (EFI_ERROR (Status)) {
01682     gBS->FreePool (ConfigResp);
01683     return Status;
01684   }
01685   EfiCopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
01686 
01687   //
01688   // Convert <ConfigResp> to buffer data
01689   //
01690   Status = HiiConfigRouting->ConfigToBlock (
01691                                HiiConfigRouting,
01692                                ConfigResp,
01693                                Buffer,
01694                                BufferSize,
01695                                &Progress
01696                                );
01697   gBS->FreePool (ConfigResp);
01698 
01699   return Status;
01700 }
01701 
01702 EFI_STATUS
01703 SetBrowserData (
01704   EFI_GUID                   *VariableGuid, OPTIONAL
01705   CHAR16                     *VariableName, OPTIONAL
01706   UINTN                      BufferSize,
01707   UINT8                      *Buffer,
01708   CHAR16                     *RequestElement  OPTIONAL
01709   )
01710 /*++
01711 
01712 Routine Description:
01713   This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
01714 
01715 Arguments:
01716   VariableGuid   - An optional field to indicate the target variable GUID name to use.
01717   VariableName   - An optional field to indicate the target human-readable variable name.
01718   BufferSize     - Length in bytes of buffer to hold retrived data.
01719   Buffer         - Buffer to hold retrived data.
01720   RequestElement - An optional field to specify which part of the buffer data
01721                    will be send back to Browser. If NULL, the whole buffer of
01722                    data will be committed to Browser.
01723                    <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
01724 
01725 Returns:
01726   EFI_SUCCESS  - Routine success.
01727   Other        - Updating Browser uncommitted data failed.
01728 
01729 --*/
01730 {
01731   EFI_STATUS                      Status;
01732   CHAR16                          *ConfigHdr;
01733   CHAR16                          *ConfigResp;
01734   CHAR16                          *StringPtr;
01735   UINTN                           HeaderLen;
01736   UINTN                           BufferLen;
01737   CHAR16                          *Progress;
01738   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
01739   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
01740   CHAR16                          BlockName[33];
01741   CHAR16                          *ConfigRequest;
01742   CHAR16                          *Request;
01743 
01744   //
01745   // Locate protocols for use
01746   //
01747   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
01748   if (EFI_ERROR (Status)) {
01749     return Status;
01750   }
01751 
01752   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
01753   if (EFI_ERROR (Status)) {
01754     return Status;
01755   }
01756 
01757   //
01758   // Prepare <ConfigRequest>
01759   //
01760   ConfigHdr = mFakeConfigHdr;
01761   HeaderLen = EfiStrLen (ConfigHdr);
01762 
01763   if (RequestElement == NULL) {
01764     //
01765     // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
01766     //
01767     BlockName[0] = L'\0';
01768     EfiStrCpy (BlockName, L"&OFFSET=0&WIDTH=");
01769 
01770     //
01771     // String lenghth of L"&OFFSET=0&WIDTH=" is 16
01772     //
01773     StringPtr = BlockName + 16;
01774     BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
01775     BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
01776 
01777     Request = BlockName;
01778   } else {
01779     Request = RequestElement;
01780   }
01781 
01782   BufferLen = HeaderLen * sizeof (CHAR16) + EfiStrSize (Request);
01783   ConfigRequest = EfiLibAllocateZeroPool (BufferLen);
01784 
01785   EfiCopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
01786   StringPtr = ConfigRequest + HeaderLen;
01787   EfiStrCpy (StringPtr, Request);
01788 
01789   //
01790   // Convert buffer to <ConfigResp>
01791   //
01792   Status = HiiConfigRouting->BlockToConfig (
01793                                 HiiConfigRouting,
01794                                 ConfigRequest,
01795                                 Buffer,
01796                                 BufferSize,
01797                                 &ConfigResp,
01798                                 &Progress
01799                                 );
01800   if (EFI_ERROR (Status)) {
01801     gBS->FreePool (ConfigRequest);
01802     return Status;
01803   }
01804 
01805   //
01806   // Skip <ConfigHdr> and '&'
01807   //
01808   StringPtr = ConfigResp + HeaderLen + 1;
01809 
01810   //
01811   // Change uncommitted data in Browser
01812   //
01813   Status = FormBrowser2->BrowserCallback (
01814                            FormBrowser2,
01815                            &BufferSize,
01816                            StringPtr,
01817                            FALSE,
01818                            VariableGuid,
01819                            VariableName
01820                            );
01821   gBS->FreePool (ConfigResp);
01822   gBS->FreePool (ConfigRequest);
01823   return Status;
01824 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines