/*++

Copyright (c) 2006, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name: 

  DeviceManager.c

Abstract:

  The platform device manager reference implement

--*/
#include "DeviceManager.h"

STATIC UINT16                     mTokenCount;
EFI_FRONTPAGE_CALLBACK_INFO       FPCallbackInfo;
extern UINTN                      gCallbackKey;
extern EFI_FORM_BROWSER_PROTOCOL  *gBrowser;
extern EFI_GUID                   gBdsStringPackGuid;
extern BOOLEAN                    gConnectAllHappened;

STRING_REF                        gStringTokenTable[] = {
  STR_VIDEO_DEVICE,
  STR_NETWORK_DEVICE,
  STR_INPUT_DEVICE,
  STR_ON_BOARD_DEVICE,
  STR_OTHER_DEVICE,
  STR_EMPTY_STRING,
  0xFFFF
};

EFI_STATUS
EFIAPI
DeviceManagerCallbackRoutine (
  IN EFI_FORM_CALLBACK_PROTOCOL       *This,
  IN UINT16                           KeyValue,
  IN EFI_IFR_DATA_ARRAY               *DataArray,
  OUT EFI_HII_CALLBACK_PACKET         **Packet
  )
/*++

Routine Description:

  This is the function that is called to provide results data to the driver.  This data
  consists of a unique key which is used to identify what data is either being passed back
  or being asked for. 

Arguments:

  KeyValue -        A unique value which is sent to the original exporting driver so that it
                    can identify the type of data to expect.  The format of the data tends to
                    vary based on the op-code that geerated the callback.

  Data -            A pointer to the data being sent to the original exporting driver.

Returns: 

--*/
{
  //
  // The KeyValue corresponds in this case to the handle which was requested to be displayed
  //
  EFI_FRONTPAGE_CALLBACK_INFO *CallbackInfo;

  CallbackInfo = EFI_FP_CALLBACK_DATA_FROM_THIS (This);
  switch (KeyValue) {
  case 0x2000:
    CallbackInfo->Data.VideoBIOS = (UINT8) (UINTN) (((EFI_IFR_DATA_ENTRY *)(DataArray + 1))->Data);
    gRT->SetVariable (
          L"VBIOS",
          &gEfiGlobalVariableGuid,
          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
          sizeof (UINT8),
          &CallbackInfo->Data.VideoBIOS
          );
    break;

  default:
    break;
  }

  gCallbackKey = KeyValue;
  return EFI_SUCCESS;
}

EFI_STATUS
InitializeDeviceManager (
  VOID
  )
/*++

Routine Description:

  Initialize HII information for the FrontPage

Arguments:
  None
            
Returns:

--*/
{
  EFI_STATUS          Status;
  EFI_HII_PACKAGES    *PackageList;
  EFI_HII_UPDATE_DATA *UpdateData;

  //
  // Allocate space for creation of UpdateData Buffer
  //
  UpdateData = AllocateZeroPool (0x1000);
  ASSERT (UpdateData != NULL);

  PackageList = PreparePackages (1, &gBdsStringPackGuid, DeviceManagerVfrBin);
  Status      = Hii->NewPack (Hii, PackageList, &FPCallbackInfo.DevMgrHiiHandle);
  gBS->FreePool (PackageList);

  //
  // This example does not implement worker functions for the NV accessor functions.  Only a callback evaluator
  //
  FPCallbackInfo.Signature                = EFI_FP_CALLBACK_DATA_SIGNATURE;
  FPCallbackInfo.DevMgrCallback.NvRead    = NULL;
  FPCallbackInfo.DevMgrCallback.NvWrite   = NULL;
  FPCallbackInfo.DevMgrCallback.Callback  = DeviceManagerCallbackRoutine;

  //
  // Install protocol interface
  //
  FPCallbackInfo.CallbackHandle = NULL;

  Status = gBS->InstallProtocolInterface (
                  &FPCallbackInfo.CallbackHandle,
                  &gEfiFormCallbackProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  &FPCallbackInfo.DevMgrCallback
                  );

  ASSERT_EFI_ERROR (Status);

  //
  // Flag update pending in FormSet
  //
  UpdateData->FormSetUpdate = TRUE;
  //
  // Register CallbackHandle data for FormSet
  //
  UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FPCallbackInfo.CallbackHandle;
  //
  // Simply registering the callback handle
  //
  Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);

  gBS->FreePool (UpdateData);
  return Status;
}

EFI_STATUS
CallDeviceManager (
  VOID
  )
/*++

Routine Description:
  
  Call the browser and display the device manager

Arguments:
  
  None
  
Returns:
  EFI_SUCCESS            - Operation is successful.
  EFI_INVALID_PARAMETER  - If the inputs to SendForm function is not valid.
  
--*/
{
  EFI_STATUS          Status;
  UINTN               BufferSize;
  UINTN               Count;
  EFI_HII_HANDLE      Index;
  UINT8               *Buffer;
  EFI_IFR_FORM_SET    *FormSetData;
  CHAR16              *String;
  UINTN               StringLength;
  EFI_HII_UPDATE_DATA *UpdateData;
  STRING_REF          Token;
  STRING_REF          TokenHelp;
  IFR_OPTION          *IfrOptionList;
  UINT8               *VideoOption;
  UINTN               VideoOptionSize;
  EFI_HII_HANDLE      *HiiHandles;
  UINT16              HandleBufferLength;
  BOOLEAN	          BootDeviceMngrMenuResetRequired;

  IfrOptionList       = NULL;
  VideoOption         = NULL;
  HiiHandles          = NULL;
  HandleBufferLength  = 0;

  //
  // Connect all prior to entering the platform setup menu.
  //
  if (!gConnectAllHappened) {
    BdsLibConnectAllDriversToAllControllers ();
    gConnectAllHappened = TRUE;
  }
  //
  // Allocate space for creation of UpdateData Buffer
  //
  UpdateData = AllocateZeroPool (0x1000);
  ASSERT (UpdateData != NULL);

  Status        = EFI_SUCCESS;
  Buffer        = NULL;
  FormSetData   = NULL;
  gCallbackKey  = 0;
  if (mTokenCount == 0) {
    Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &mTokenCount, L" ");
  }

  Token     = mTokenCount;
  TokenHelp = (UINT16) (Token + 1);

  //
  // Reset the menu
  //
  for (Index = 0, Count = 1; Count < 0x10000; Count <<= 1, Index++) {
    //
    // We will strip off all previous menu entries
    //
    UpdateData->DataCount = 0xFF;

    //
    // Erase entries on this label
    //
    Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, FALSE, UpdateData);

    //
    // Did we reach the end of the Token Table?
    //
    if (gStringTokenTable[Index] == 0xFFFF) {
      break;
    }

    CreateSubTitleOpCode (gStringTokenTable[Index], &UpdateData->Data);
    //
    // Add a single menu item - in this case a subtitle for the device type
    //
    UpdateData->DataCount = 1;

    //
    // Add default title for this label
    //
    Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);
  }
  //
  // Add a space and an exit string.  Remember since we add things at the label and push other things beyond the
  // label down, we add this in reverse order
  //
  CreateSubTitleOpCode (STRING_TOKEN (STR_EXIT_STRING), &UpdateData->Data);
  Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);
  CreateSubTitleOpCode (STR_EMPTY_STRING, &UpdateData->Data);
  Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);

  //
  // Get all the Hii handles
  //
  Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandles);
  ASSERT_EFI_ERROR (Status);

  for (Index = 1, BufferSize = 0; Index < HandleBufferLength; Index++) {
    //
    // Am not initializing Buffer since the first thing checked is the size
    // this way I can get the real buffersize in the smallest code size
    //
    Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);

    if (Status != EFI_NOT_FOUND) {
      //
      // BufferSize should have the real size of the forms now
      //
      Buffer = AllocateZeroPool (BufferSize);
      ASSERT (Buffer != NULL);

      //
      // Am not initializing Buffer since the first thing checked is the size
      // this way I can get the real buffersize in the smallest code size
      //
      Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);

      //
      // Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data.
      //
      FormSetData = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACK_HEADER));

      //
      // If this formset belongs in the device manager, add it to the menu
      //
      if (FormSetData->Class != EFI_NON_DEVICE_CLASS) {

        StringLength  = 0x1000;
        String        = AllocateZeroPool (StringLength);
        ASSERT (String != NULL);

        Status  = Hii->GetString (Hii, Index, FormSetData->FormSetTitle, TRUE, NULL, &StringLength, String);
        Status  = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);

        //
        // If token value exceeded real token value - we need to add a new token values
        //
        if (Status == EFI_INVALID_PARAMETER) {
          Token     = 0;
          TokenHelp = 0;
          Status    = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);
        }

        StringLength = 0x1000;
        if (FormSetData->Help == 0) {
          TokenHelp = 0;
        } else {
          Status = Hii->GetString (Hii, Index, FormSetData->Help, TRUE, NULL, &StringLength, String);
          if (StringLength == 0x02) {
            TokenHelp = 0;
          } else {
            Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);
            if (Status == EFI_INVALID_PARAMETER) {
              TokenHelp = 0;
              Status    = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);
            }
          }
        }

        gBS->FreePool (String);

        CreateGotoOpCode (
          0x1000,     // Device Manager Page
          Token,      // Description String Token
          TokenHelp,  // Description Help String Token
          EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,  // Flag designating callback is active
          (UINT16) Index,                                     // Callback key value
          &UpdateData->Data                                   // Buffer to fill with op-code
          );

        //
        // In the off-chance that we have lots of extra tokens allocated to the DeviceManager
        // this ensures we are fairly re-using the tokens instead of constantly growing the token
        // storage for this one handle.  If we incremented the token value beyond what it normally
        // would use, we will fall back into the error path which seeds the token value with a 0
        // so that we can correctly add a token value.
        //
        if (TokenHelp == 0) {
          //
          // Since we didn't add help, only advance Token by 1
          //
          Token++;
        } else {
          Token     = (UINT16) (Token + 2);
          TokenHelp = (UINT16) (TokenHelp + 2);
        }
        //
        // This for loop basically will take the Class value which is a bitmask and
        // update the form for every active bit.  There will be a label at each bit
        // location.  So if someone had a device which a class of EFI_DISK_DEVICE_CLASS |
        // EFI_ON_BOARD_DEVICE_CLASS, this routine will unwind that mask and drop the menu entry
        // on each corresponding label.
        //
        for (Count = 1; Count < 0x10000; Count <<= 1) {
          //
          // This is an active bit, so update the form
          //
          if (FormSetData->Class & Count) {
            Hii->UpdateForm (
                  Hii,
                  FPCallbackInfo.DevMgrHiiHandle,
                  (EFI_FORM_LABEL) (FormSetData->Class & Count),
                  TRUE,
                  UpdateData
                  );
          }
        }
      }

      BufferSize = 0;
      //
      // Reset Buffer pointer to original location
      //
      gBS->FreePool (Buffer);
    }
  }
  //
  // Add oneof for video BIOS selection
  //
  VideoOption = BdsLibGetVariableAndSize (
                  L"VBIOS",
                  &gEfiGlobalVariableGuid,
                  &VideoOptionSize
                  );
  if (NULL == VideoOption) {
    FPCallbackInfo.Data.VideoBIOS = 0;
  } else {
    FPCallbackInfo.Data.VideoBIOS = VideoOption[0];
    gBS->FreePool (VideoOption);
  }

  ASSERT (FPCallbackInfo.Data.VideoBIOS <= 1);

  Status = gBS->AllocatePool (EfiBootServicesData, 2 * sizeof (IFR_OPTION), (VOID**) &IfrOptionList);
  if (IfrOptionList != NULL) {
    IfrOptionList[0].Flags        = EFI_IFR_FLAG_INTERACTIVE;
    IfrOptionList[0].Key          = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;
    IfrOptionList[0].StringToken  = STRING_TOKEN (STR_ONE_OF_PCI);
    IfrOptionList[0].Value        = 0;
    IfrOptionList[0].OptionString = NULL;
    IfrOptionList[1].Flags        = EFI_IFR_FLAG_INTERACTIVE;
    IfrOptionList[1].Key          = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;
    IfrOptionList[1].StringToken  = STRING_TOKEN (STR_ONE_OF_AGP);
    IfrOptionList[1].Value        = 1;
    IfrOptionList[1].OptionString = NULL;
    IfrOptionList[FPCallbackInfo.Data.VideoBIOS].Flags |= EFI_IFR_FLAG_DEFAULT;

    CreateOneOfOpCode (
      SET_VIDEO_BIOS_TYPE_QUESTION_ID,
      (UINT8) 1,
      STRING_TOKEN (STR_ONE_OF_VBIOS),
      STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),
      IfrOptionList,
      2,
      &UpdateData->Data
      );

    UpdateData->DataCount = 4;
    Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) EFI_VBIOS_CLASS, TRUE, UpdateData);
    gBS->FreePool (IfrOptionList);
  }

  BootDeviceMngrMenuResetRequired = FALSE;
  Status = gBrowser->SendForm (
                      gBrowser,
                      TRUE,                             // Use the database
                      &FPCallbackInfo.DevMgrHiiHandle,  // The HII Handle
                      1,
                      NULL,
                      FPCallbackInfo.CallbackHandle,
                      (UINT8 *) &FPCallbackInfo.Data,
                      NULL,
                      &BootDeviceMngrMenuResetRequired
                      );

  if (BootDeviceMngrMenuResetRequired) {
    EnableResetRequired ();
  }

  Hii->ResetStrings (Hii, FPCallbackInfo.DevMgrHiiHandle);

  //
  // We will have returned from processing a callback - user either hit ESC to exit, or selected
  // a target to display
  //
  if (gCallbackKey != 0 && gCallbackKey < 0x2000) {
    BootDeviceMngrMenuResetRequired = FALSE;
    Status = gBrowser->SendForm (
                        gBrowser,
                        TRUE,                             // Use the database
                        (EFI_HII_HANDLE *) &gCallbackKey, // The HII Handle
                        1,
                        NULL,
                        NULL,                             // This is the handle that the interface to the callback was installed on
                        NULL,
                        NULL,
                        &BootDeviceMngrMenuResetRequired
                        );

    if (BootDeviceMngrMenuResetRequired) {
      EnableResetRequired ();
    }
    //
    // Force return to Device Manager
    //
    gCallbackKey = 4;
  }

  if (gCallbackKey >= 0x2000) {
    gCallbackKey = 4;
  }

  gBS->FreePool (UpdateData);
  gBS->FreePool (HiiHandles);

  return Status;
}
