/*++

Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
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:

  IfrParse.c  

Abstract:

  Routines for parsing and managing HII IFR packs.

--*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "Tiano.h"
#include "EfiUtilityMsgs.h"
#include "EfiInternalFormRepresentation.h"
#include "Hii.h"
#include "IfrParse.h"
#include "HiiPack.h"

typedef struct _VARIABLE_STORE_ENTRY {
  struct _VARIABLE_STORE_ENTRY  *Next;
  CHAR8                         VarName[MAX_VARIABLE_NAME];
  char                          *VarBuffer;
  int                           VarBufferSize;
  EFI_HII_VARIABLE_PACK         *VarPack;
  int                           VarPackSize;
} VARIABLE_STORE_ENTRY;

typedef STATUS (*IFR_PARSE_FUNCTION) (IFR_PARSE_CONTEXT * Context);

typedef struct {
  INT8                *Name;
  INT32               Size;
  IFR_PARSE_FUNCTION  Parse;
} IFR_PARSE_TABLE_ENTRY;

static
STATUS
IfrParse01 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse02 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse03 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse05 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse06 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse07 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse08 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse09 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse0A (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse0B (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse0C (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse0D (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse0E (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse0F (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse10 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse11 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse12 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse13 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse14 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse15 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse16 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse17 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse18 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse19 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse1A (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse1B (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse1C (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse1D (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse1E (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse1F (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse20 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse21 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse22 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse23 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse24 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse25 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse26 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse27 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse28 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse29 (
  IFR_PARSE_CONTEXT *Context
  );
static
STATUS
IfrParse2A (
  IFR_PARSE_CONTEXT *Context
  );

static const IFR_PARSE_TABLE_ENTRY  mIfrParseTable[] = {
  {
    0,
    0,
    NULL
  },  // invalid
  {
    "EFI_IFR_FORM",
    sizeof (EFI_IFR_FORM),
    IfrParse01
  },
  {
    "EFI_IFR_SUBTITLE",
    sizeof (EFI_IFR_SUBTITLE),
    IfrParse02
  },
  {
    "EFI_IFR_TEXT",
    -6,
    IfrParse03
  },  // sizeof (EFI_IFR_TEXT) },
  {
    "unused 0x04 opcode",
    0,
    NULL
  },  // EFI_IFR_GRAPHIC_OP
  {
    "EFI_IFR_ONE_OF",
    sizeof (EFI_IFR_ONE_OF),
    IfrParse05
  },
  {
    "EFI_IFR_CHECK_BOX",
    sizeof (EFI_IFR_CHECK_BOX),
    IfrParse06
  },
  {
    "EFI_IFR_NUMERIC",
    sizeof (EFI_IFR_NUMERIC),
    IfrParse07
  },
  {
    "EFI_IFR_PASSWORD",
    sizeof (EFI_IFR_PASSWORD),
    IfrParse08
  },
  {
    "EFI_IFR_ONE_OF_OPTION",
    sizeof (EFI_IFR_ONE_OF_OPTION),
    IfrParse09
  },
  {
    "EFI_IFR_SUPPRESS",
    sizeof (EFI_IFR_SUPPRESS),
    IfrParse0A
  },
  {
    "EFI_IFR_END_FORM",
    sizeof (EFI_IFR_END_FORM),
    IfrParse0B
  },
  {
    "EFI_IFR_HIDDEN",
    sizeof (EFI_IFR_HIDDEN),
    IfrParse0C
  },
  {
    "EFI_IFR_END_FORM_SET",
    sizeof (EFI_IFR_END_FORM_SET),
    IfrParse0D
  },
  {
    "EFI_IFR_FORM_SET",
    sizeof (EFI_IFR_FORM_SET),
    IfrParse0E
  },
  {
    "EFI_IFR_REF",
    sizeof (EFI_IFR_REF),
    IfrParse0F
  },
  {
    "EFI_IFR_END_ONE_OF",
    sizeof (EFI_IFR_END_ONE_OF),
    IfrParse10
  },
  {
    "EFI_IFR_INCONSISTENT",
    sizeof (EFI_IFR_INCONSISTENT),
    IfrParse11
  },
  {
    "EFI_IFR_EQ_ID_VAL",
    sizeof (EFI_IFR_EQ_ID_VAL),
    IfrParse12
  },
  {
    "EFI_IFR_EQ_ID_ID",
    sizeof (EFI_IFR_EQ_ID_ID),
    IfrParse13
  },
  {
    "EFI_IFR_EQ_ID_LIST",
    -(int) (sizeof (EFI_IFR_EQ_ID_LIST)),
    IfrParse14
  },
  {
    "EFI_IFR_AND",
    sizeof (EFI_IFR_AND),
    IfrParse15
  },
  {
    "EFI_IFR_OR",
    sizeof (EFI_IFR_OR),
    IfrParse16
  },
  {
    "EFI_IFR_NOT",
    sizeof (EFI_IFR_NOT),
    IfrParse17
  },
  {
    "EFI_IFR_END_IF",
    sizeof (EFI_IFR_END_IF),
    IfrParse18
  },
  {
    "EFI_IFR_GRAYOUT",
    sizeof (EFI_IFR_GRAYOUT),
    IfrParse19
  },
  {
    "EFI_IFR_DATE",
    sizeof (EFI_IFR_DATE) / 3,
    IfrParse1A
  },
  {
    "EFI_IFR_TIME",
    sizeof (EFI_IFR_TIME) / 3,
    IfrParse1B
  },
  {
    "EFI_IFR_STRING",
    sizeof (EFI_IFR_STRING),
    IfrParse1C
  },
  {
    "EFI_IFR_LABEL",
    sizeof (EFI_IFR_LABEL),
    IfrParse1D
  },
  {
    "EFI_IFR_SAVE_DEFAULTS",
    sizeof (EFI_IFR_SAVE_DEFAULTS),
    IfrParse1E
  },
  {
    "EFI_IFR_RESTORE_DEFAULTS",
    sizeof (EFI_IFR_RESTORE_DEFAULTS),
    IfrParse1F
  },
  {
    "EFI_IFR_BANNER",
    sizeof (EFI_IFR_BANNER),
    IfrParse20
  },
  {
    "EFI_IFR_INVENTORY",
    sizeof (EFI_IFR_INVENTORY),
    IfrParse21
  },
  {
    "EFI_IFR_EQ_VAR_VAL_OP",
    sizeof (EFI_IFR_EQ_VAR_VAL),
    IfrParse22
  },
  {
    "EFI_IFR_ORDERED_LIST_OP",
    sizeof (EFI_IFR_ORDERED_LIST),
    IfrParse23
  },
  {
    "EFI_IFR_VARSTORE_OP",
    -(int) (sizeof (EFI_IFR_VARSTORE)),
    IfrParse24
  },
  {
    "EFI_IFR_VARSTORE_SELECT_OP",
    sizeof (EFI_IFR_VARSTORE_SELECT),
    IfrParse25
  },
  {
    "EFI_IFR_VARSTORE_SELECT_PAIR_OP",
    sizeof (EFI_IFR_VARSTORE_SELECT_PAIR),
    IfrParse26
  },
  {
    "EFI_IFR_TRUE",
    sizeof (EFI_IFR_TRUE),
    IfrParse27
  },
  {
    "EFI_IFR_FALSE",
    sizeof (EFI_IFR_FALSE),
    IfrParse28
  },
  {
    "EFI_IFR_GT",
    sizeof (EFI_IFR_GT),
    IfrParse29
  },
  {
    "EFI_IFR_GE",
    sizeof (EFI_IFR_GE),
    IfrParse2A
  },
};
#define PARSE_TABLE_ENTRIES (sizeof (mIfrParseTable) / sizeof (mIfrParseTable[0]))

static
STATUS
GetVarStoreInfo (
  IFR_PARSE_CONTEXT   *Context,
  UINT16              VarId,
  EFI_GUID            **VarStoreGuid,
  char                **VarStoreName
  );

static
void
FreeVarStores (
  VOID
  );

static
STATUS
CreateVarStore (
  EFI_GUID *VarGuid,
  CHAR8    *VarName,
  int      VarStoreSize
  );

static
STATUS
SetDefaults (
  IFR_PARSE_CONTEXT *Context,
  UINT32            MfgDefaults
  );

//
// Globals
//
static IFR_PARSE_CONTEXT            *mParseContext    = NULL;
static VARIABLE_STORE_ENTRY         *mVariableStores  = NULL;
static int                          BreakOnOpcodeTag  = 0;
static int                          OpcodeTag         = 1;

/*****************************************************************************/
STATUS
IfrParseCheck (
  char    *Buffer,
  long    BufferSize
  )
/*++

Routine Description:

  Check a buffer to ensure that is is parseable IFR
  
Arguments:

  Buffer      - pointer to raw IFR bytes
  BufferSize  - size of IFR pointed to by Buffer

Returns:

  STATUS_SUCCESS      if successful
  STATUS_ERROR        otherwise
  
--*/
{
  char              *Start;

  char              *End;

  char              *Pos;
  EFI_IFR_OP_HEADER *OpHeader;
  char              *FileName;
  FileName = "";
  //
  // Walk the list of IFR statements in the IFR pack
  //
  Start = Buffer;
  Pos   = Buffer;
  End   = Start + BufferSize;
  while ((Pos >= Start) && (Pos < End)) {
    OpHeader = (EFI_IFR_OP_HEADER *) Pos;
    //
    // Check range on size
    //
    if (Pos + OpHeader->Length > End) {
      Error (NULL, 0, 0, FileName, "invalid IFR opcode size at offset 0x%X", (int) Pos - (int) Start);
      return STATUS_ERROR;
    }

    if (OpHeader->Length == 0) {
      Error (NULL, 0, 0, FileName, "IFR opcode size=0 at offset 0x%X", (int) Pos - (int) Start);
      return STATUS_ERROR;
    }
    //
    // See if it's the END_FORMSET opcode
    //
    if (OpHeader->OpCode == EFI_IFR_END_FORM_SET_OP) {
      break;
    }
    //
    // Advance to next IFR statement/opcode
    //
    Pos += OpHeader->Length;
  }

  return STATUS_SUCCESS;
}

STATUS
IfrParseInit (
  VOID
  )
/*++

Routine Description:

  Initialize this module for IFR pack parsing
  
Arguments:

Returns:

  STATUS_SUCCESS      always
  
--*/
{
  return STATUS_SUCCESS;
}

STATUS
IfrParseEnd (
  VOID
  )
/*++

Routine Description:

  Free up memory allocated during IFR pack parsing done by this module
  
Arguments:
  None

Returns:

  STATUS_SUCCESS      always
  
--*/
{
  IFR_PARSE_CONTEXT *NextContext;
  IFR_PARSE_ENTRY   *NextEntry;
  //
  // Free up the memory from our parse contexts
  //
  while (mParseContext != NULL) {
    while (mParseContext->Ifr != NULL) {
      NextEntry = mParseContext->Ifr->Next;
      //
      // We pointed directly into the user buffer, rather than make
      // a copy, so don't free up the bytes.
      //
      free (mParseContext->Ifr);
      mParseContext->Ifr = NextEntry;
    }

    NextContext = mParseContext->Next;
    free (mParseContext->PackHeader);
    free (mParseContext);
    mParseContext = NextContext;
  }

  return STATUS_SUCCESS;
}

static
void
FreeVarStores (
  VOID
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  None

Returns:

  GC_TODO: add return values

--*/
{
  VARIABLE_STORE_ENTRY  *NextVarStore;
  //
  // Free up memory from our variable stores
  //
  while (mVariableStores != NULL) {
    if (mVariableStores->VarPack != NULL) {
      free (mVariableStores->VarPack);
    }

    NextVarStore = mVariableStores->Next;
    free (mVariableStores);
    mVariableStores = NextVarStore;
  }
}

/******************************************************************************
  FUNCTION: IfrParsePack() 
   
  DESCRIPTION:  Given a pointer to an IFR pack, parse it to create a linked
    list of opcodes and relevant data required for later dumping.


*******************************************************************************/
STATUS
IfrParsePack (
  int               Handle,
  EFI_HII_IFR_PACK  *PackHeader,
  EFI_GUID          *PackageGuid
  )
/*++

Routine Description:

  Given a pointer to an IFR pack, parse it to create a linked
  list of opcodes and relevant data required for later dumping.
  
Arguments:

  Handle          - the handle number associated with this IFR pack. It
                    can be used later to retrieve more info on the particular
                    pack
  PackHeader      - pointer to IFR pack to parse
  PackageGuid     - on input, it comes from the HII data table entry for this pack. 
                    On output, we'll return the IFR formset GUID.

Returns:

  STATUS_SUCCESS      always

--*/
{
  EFI_IFR_OP_HEADER *OpHeader;
  IFR_PARSE_CONTEXT *Context;
  IFR_PARSE_CONTEXT *TempContext;
  IFR_PARSE_ENTRY   *IfrEntry;
  //
  // Initialize our context
  //
  Context = (IFR_PARSE_CONTEXT *) malloc (sizeof (IFR_PARSE_CONTEXT));
  if (Context == NULL) {
    Error (NULL, 0, 0, "memory allocation failure", NULL);
    return STATUS_ERROR;
  }

  memset ((void *) Context, 0, sizeof (IFR_PARSE_CONTEXT));
  //
  // Cache a copy of the input pack so the caller can free their copy
  //
  Context->PackHeader = (EFI_HII_IFR_PACK *) malloc (PackHeader->Header.Length);
  if (Context->PackHeader == NULL) {
    Error (NULL, 0, 0, "memory allocation failure", NULL);
    free (Context);
    return STATUS_ERROR;
  }

  memcpy (Context->PackHeader, PackHeader, PackHeader->Header.Length);
  Context->IfrBufferStart = (char *) (Context->PackHeader + 1);
  Context->CurrentPos     = Context->IfrBufferStart;
  Context->IfrBufferLen   = PackHeader->Header.Length - sizeof (EFI_HII_IFR_PACK);
  Context->Handle         = Handle;
  Context->FormsetGuid    = &Context->NullGuid;
  Context->PackageGuid    = *PackageGuid;
  //
  // Add it to the end of our list
  //
  if (mParseContext == NULL) {
    mParseContext = Context;
  } else {
    TempContext = mParseContext;
    while (TempContext->Next != NULL) {
      TempContext = TempContext->Next;
    }

    TempContext->Next = Context;
  }
  //
  // Walk the opcodes in the pack
  //
  while
  (
    (Context->CurrentPos >= Context->IfrBufferStart) &&
    (Context->CurrentPos < Context->IfrBufferStart + Context->IfrBufferLen)
  ) {
    OpHeader = (EFI_IFR_OP_HEADER *) Context->CurrentPos;
    //
    // Allocate a new IFR entry to put in our linked list, then
    // point directly to the caller's raw data.
    //
    IfrEntry = (IFR_PARSE_ENTRY *) malloc (sizeof (IFR_PARSE_ENTRY));
    if (IfrEntry == NULL) {
      Error (NULL, 0, 0, "memory allocation failure", NULL);
      free (Context->PackHeader);
      free (Context);
      return STATUS_ERROR;
    }

    memset ((void *) IfrEntry, 0, sizeof (IFR_PARSE_ENTRY));
    IfrEntry->Tag = ++OpcodeTag;
    if (OpcodeTag == BreakOnOpcodeTag) {
      EFI_BREAKPOINT ();
    }

    IfrEntry->RawIfrHeader = (EFI_IFR_OP_HEADER *) (Context->CurrentPos);
    //
    // Add this entry to our linked list. If it's not the first, then
    // forward the variable store settings from the previous entry.
    //
    if (Context->LastIfr != NULL) {
      IfrEntry->VarStoreGuid1 = Context->LastIfr->VarStoreGuid1;
      IfrEntry->VarStoreName1 = Context->LastIfr->VarStoreName1;
      IfrEntry->VarStoreGuid2 = Context->LastIfr->VarStoreGuid2;
      IfrEntry->VarStoreName2 = Context->LastIfr->VarStoreName2;
      Context->LastIfr->Next  = IfrEntry;
    } else {
      Context->Ifr = IfrEntry;
    }

    Context->LastIfr = IfrEntry;
    //
    // Switch on the opcode to parse it
    //
    if (OpHeader->OpCode < PARSE_TABLE_ENTRIES) {
      if (mIfrParseTable[OpHeader->OpCode].Parse != NULL) {
        mIfrParseTable[OpHeader->OpCode].Parse (Context);
      }
    } else {
      Error (
        NULL,
        0,
        0,
        "invalid opcode found in IFR",
        "offset=0x%X opcode=0x%02X",
        (int) OpHeader - (int) Context->PackHeader,
        (int) OpHeader->OpCode
        );
      free (IfrEntry);
      free (Context->PackHeader);
      free (Context);
      return STATUS_ERROR;
    }
    //
    // If it's the END_FORMSET opcode, then we're done
    //
    if (OpHeader->OpCode == EFI_IFR_END_FORM_SET_OP) {
      break;
    }
    //
    // Advance to next IFR statement/opcode
    //
    if (OpHeader->Length == 0) {
      Error (NULL, 0, 0, "0-length IFR opcode encountered", NULL);
      free (IfrEntry);
      free (Context->PackHeader);
      free (Context);
      return STATUS_ERROR;
    }

    Context->CurrentPos += OpHeader->Length;
  }
  //
  // Return the form GUID.
  //
  *PackageGuid = *Context->FormsetGuid;  
  return STATUS_SUCCESS;
}

/******************************************************************************
  FUNCTION:  GetVarStoreInfo()
   
  DESCRIPTION:  IFR contains VARSTORE opcodes to specify where variable data 
    for following opcodes is supposed to be stored. One VARSTORE statement
    allows you to specify the variable store GUID and a key, and another
    VARSTORE (select) allows you to specify the key of a VARSTORE statement. 
    Given the key from a VARSTORE_SELECT statement, go find the corresponding
    VARSTORE statement with a matching key and return the varstore GUID and 
    name. If key == 0, then the variable store is FormsetGuid."Setup"
*******************************************************************************/
static
STATUS
GetVarStoreInfo (
  IFR_PARSE_CONTEXT     *Context,
  UINT16                VarId,
  EFI_GUID              **VarStoreGuid,
  char                  **VarStoreName
  )
/*++

Routine Description:

  Get variable store information from an IFR pack for a given variable store ID.
  
Arguments:

  Context       - pointer to IFR parse context
  VarId         - variable store ID referenced by IFR being parsed
  VarStoreGuid  - outgoing GUID of the variable store corresponding to VarId
  VarStoreName  - outgoing variable name of variable store corresponding to VarId

Returns:

  STATUS_SUCCESS      - variable store with matching VarId found, and outoing GUID/Name are valid
  STATUS_ERROR        - otherwise

--*/
{
  IFR_PARSE_ENTRY   *Ptr;
  EFI_IFR_VARSTORE  *VarStore;
  if (Context == NULL) {
    return STATUS_ERROR;
  }

  //
  // Walk the entire IFR form and find a variable store opcode that
  // has a matching variable store ID.
  //
  for (Ptr = Context->Ifr; Ptr != NULL; Ptr = Ptr->Next) {
    if (Ptr->RawIfrHeader->OpCode == EFI_IFR_FORM_SET_OP) {
      if (VarId == 0) {
        *VarStoreGuid = &((EFI_IFR_FORM_SET *) (Ptr->RawIfrHeader))->Guid;
        *VarStoreName = DEFAULT_VARIABLE_NAME;
        return STATUS_SUCCESS;
      }
    } else if (Ptr->RawIfrHeader->OpCode == EFI_IFR_VARSTORE_OP) {
      //
      // See if it's a variable ID match
      //
      VarStore = (EFI_IFR_VARSTORE *) Ptr->RawIfrHeader;
      if (VarStore->VarId == VarId) {
        *VarStoreGuid = &VarStore->Guid;
        *VarStoreName = (char *) (VarStore + 1);
        return STATUS_SUCCESS;
      }
    }
  }

  return STATUS_ERROR;
}

STATUS
IfrSetDefaults (
  int MfgDefaults
  )
/*++

Routine Description:

  Go through all the IFR forms we've parsed so far and create and set variable
  defaults.
  
Arguments:

  MfgDefaults   - non-zero if manufacturing defaults are desired

Returns:

  STATUS_SUCCESS      - always

--*/
{
  IFR_PARSE_CONTEXT *Context;
  //
  // First free up any variable stores we've created so far.
  //
  FreeVarStores ();
  for (Context = mParseContext; Context != NULL; Context = Context->Next) {
    //
    // Call our internal function to handle it
    //
    SetDefaults (Context, MfgDefaults);
  }

  return STATUS_SUCCESS;

}

/******************************************************************************/
STATUS
IfrGetIfrPack (
  int               Handle,
  EFI_HII_IFR_PACK  **PackHeader,
  EFI_GUID          *FormsetGuid
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Handle      - GC_TODO: add argument description
  PackHeader  - GC_TODO: add argument description
  FormsetGuid - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  IFR_PARSE_CONTEXT *Context;

  for (Context = mParseContext; Context != NULL; Context = Context->Next) {
    if (Context->Handle == Handle) {
      *PackHeader = Context->PackHeader;
      memcpy (FormsetGuid, Context->FormsetGuid, sizeof (EFI_GUID));
      return STATUS_SUCCESS;
    }
  }

  return STATUS_ERROR;
}

STATUS
IfrReferencesVarPack (
  int                   IfrHandle,
  EFI_HII_VARIABLE_PACK *VarPack
  )
/*++

Routine Description:

  Given an HII handle number (which corrresponds to a handle number passed 
  in to IfrParsePack()), see if the IFR references the specified variable
  pack.
  
Arguments:

  IfrHandle   - handle number for the IFR pack to check (passed to IfrParsePack())
  VarPack     - variable pack to check to see if the IFR references

Returns:

  STATUS_SUCCESS      if the IFR on the given handle references the variable pack
  STATUS_WARNING      the IFR does not reference the variable pack
  STATUS_ERROR        invalid IFR handle
  
--*/
{
  IFR_PARSE_CONTEXT *Context;
  char              VarName[MAX_VARIABLE_NAME];
  IFR_PARSE_ENTRY   *ParseEntry;

  for (Context = mParseContext; Context != NULL; Context = Context->Next) {
    if (Context->Handle == IfrHandle) {
      //
      // Create an ASCII version of the variable name, since that's what is
      // referenced in IFR.
      //
      sprintf (VarName, "%S", (CHAR16 *) (VarPack + 1));
      //
      // Walk all the opcodes and see if the IFR references this variable pack
      //
      for (ParseEntry = Context->Ifr; ParseEntry != NULL; ParseEntry = ParseEntry->Next) {
        //
        // Check for Name.Guid match for primary IFR variable store
        //
        if ((strcmp (VarName, ParseEntry->VarStoreName1) == 0) &&
            (memcmp (&VarPack->VariableGuid, ParseEntry->VarStoreGuid1, sizeof (EFI_GUID)) == 0)
            ) {
          return STATUS_SUCCESS;
        }
        //
        // Check for Name.Guid match for secondary IFR variable store
        //
        if ((ParseEntry->VarStoreName2 != NULL) &&
            (strcmp (VarName, ParseEntry->VarStoreName2) == 0) &&
            (memcmp (&VarPack->VariableGuid, ParseEntry->VarStoreGuid2, sizeof (EFI_GUID)) == 0)
            ) {
          return STATUS_SUCCESS;
        }
      }

      return STATUS_WARNING;
    }
  }

  return STATUS_ERROR;
}

STATUS
IfrGetVarPack (
  int                     VarIndex,
  EFI_HII_VARIABLE_PACK   **VarPack
  )
/*++

Routine Description:

  Get the variable defaults. It is expected that the caller
  called IfrSetDefaults() previously to walk all the IFR forms we know about
  and create and initialize default values.
  
Arguments:

  VarIndex - a 0-based index into all the variable stores we know about
  VarPack  - outgoing pointer to a variable pack

Returns:

  STATUS_ERROR    - VarIndex exceeds the number of variable packs we know of
  STATUS_SUCCESS  - otherwise
  
--*/
{
  VARIABLE_STORE_ENTRY  *Entry;
  //
  // Initialize outgoing parameters
  //
  *VarPack = NULL;
  for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) {
    if (VarIndex == 0) {
      *VarPack = Entry->VarPack;
      return STATUS_SUCCESS;
    }

    VarIndex--;
  }

  return STATUS_ERROR;
}

static
STATUS
SetVariableValue (
  EFI_GUID    *VarGuid,
  char        *VarName,
  int         VarOffset,
  int         VarSize,
  void        *VarValue
  )
/*++

Routine Description:

  Given a variable GUID.Name, offset, size, and value, set the bytes in
  the variable to the provided value.
  
Arguments:
  VarGuid           - GUID of variable to set
  VarName           - name of variable to set
  VarOffset         - byte offset into the variable store 
  VarSize           - size of the value in the variable store (in bytes)
  VarValue          - pointer to buffer containing the value to set

Returns:

  
--*/
{
  VARIABLE_STORE_ENTRY  *Entry;
  char                  *Src;
  char                  *Dest;
  //
  // Go through our list of variable stores to find the match
  //
  for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) {
    if (memcmp (VarGuid, &Entry->VarPack->VariableGuid, sizeof (EFI_GUID)) == 0) {
      if (strcmp (VarName, Entry->VarName) == 0) {
        //
        // Found match -- check offset. If it's beyond the size of the variable store
        // buffer, then return a warning. Note that date-time can be beyond the
        // end of the varstore, which is ok.
        //
        if (VarOffset + VarSize <= Entry->VarBufferSize) {
          //
          // Stuff the data
          //
          Dest  = Entry->VarBuffer + VarOffset;
          Src   = (char *) VarValue;
          while (VarSize > 0) {
            *Dest = *Src;
            Src++;
            Dest++;
            VarSize--;
          }

          return STATUS_SUCCESS;
        }

        return STATUS_WARNING;
      }
    }
  }

  return STATUS_ERROR;
}

static
STATUS
SetDefaults (
  IFR_PARSE_CONTEXT *Context,
  UINT32            MfgDefaults
  )
/*++

Routine Description:

  Set variable defaults by walking a single IFR form.
  
Arguments:
  
  Context     - Pointer to the IFR context.
  MfgDefaults - Number of Mfg defaults

Returns:

  EFI_INVALID_PARAMETER - arguments to function are invalid
  STATUS_SUCCESS        - function executed successfully
  
--*/
{
  int                   Size;
  int                   CachedVarOffset;
  int                   CachedVarSize;
  int                   OrderedList;
  IFR_PARSE_ENTRY       *SavedParseEntry;
  EFI_IFR_CHECK_BOX     *IfrCheckBox;
  EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
  EFI_IFR_NUMERIC       *IfrNumeric;
  STATUS                Status;
  char                  ZeroByte;

  //
  // Walk the opcodes to set default values and stuff them into the variable stores
  //

  if (Context == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  Status              = STATUS_SUCCESS;
  Context->CurrentIfr = Context->Ifr;
  SavedParseEntry     = NULL;
  OrderedList         = 0;
  CachedVarOffset     = 0;
  CachedVarSize       = 0;
  ZeroByte            = 0;

  while (Context->CurrentIfr != NULL) {
    if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_FORM_SET_OP) {
      //
      // Formset opcode -- create a variable pack
      //
      Status = CreateVarStore (
                &((EFI_IFR_FORM_SET *) (Context->CurrentIfr->RawIfrHeader))->Guid,
                DEFAULT_VARIABLE_NAME,
                ((EFI_IFR_FORM_SET *) (Context->CurrentIfr->RawIfrHeader))->NvDataSize
                );
    } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_VARSTORE_OP) {
      //
      // Variable store opcode -- create a variable pack
      //
      Status = CreateVarStore (
                &((EFI_IFR_VARSTORE *) (Context->CurrentIfr->RawIfrHeader))->Guid,
                (char *) Context->CurrentIfr->RawIfrHeader + sizeof (EFI_IFR_VARSTORE),
                ((EFI_IFR_VARSTORE *) (Context->CurrentIfr->RawIfrHeader))->Size
                );
    } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ONE_OF_OP) {
      //
      // Need this parse context later when we find the default ONE_OF_OPTION.
      // Clear out the variable store first, so that we're covered if someone
      // has two one-of opcode that operate on the same data.
      // So "last one wins" is the behavior.
      //
      OrderedList     = 0;
      SavedParseEntry = Context->CurrentIfr;
      CachedVarOffset = ((EFI_IFR_ONE_OF *) Context->CurrentIfr->RawIfrHeader)->QuestionId;
      CachedVarSize   = ((EFI_IFR_ONE_OF *) Context->CurrentIfr->RawIfrHeader)->Width;
    } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ORDERED_LIST_OP) {
      //
      // Need this parse context later as we parse the ONE_OF_OP's in the ordered list
      //
      OrderedList     = 1;
      SavedParseEntry = Context->CurrentIfr;
      CachedVarOffset = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->QuestionId;
      CachedVarSize   = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->MaxEntries;

      while (CachedVarSize > 0) {
        Status = SetVariableValue (
                  SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
                  SavedParseEntry->VarStoreName1, // name of variable store to write
                  CachedVarOffset,                // offset into variable store
                  1,                              // variable data size
                  (void *) &ZeroByte
                  );
        //
        // variable value
        //
        CachedVarSize--;
        CachedVarOffset++;
      }

      CachedVarOffset = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->QuestionId;
      CachedVarSize   = 1;
      //
      // ((EFI_IFR_ORDERED_LIST *)Context->CurrentIfr->RawIfrHeader)->Width;
      //
    } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ONE_OF_OPTION_OP) {
      IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) Context->CurrentIfr->RawIfrHeader;
      //
      // If we're in an ordered list, then copy the value to the data store
      //
      if (OrderedList) {
        Status = SetVariableValue (
                  SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
                  SavedParseEntry->VarStoreName1, // name of variable store to write
                  CachedVarOffset,                // offset into variable store
                  1,                              // variable data size
                  (void *) &IfrOneOfOption->Value
                  );
        //
        // variable value
        //
        // Advance the offset for the next ordered list item
        //
        CachedVarOffset += CachedVarSize;
      } else {
        //
        // ONE-OF list. See if the default flag is set (provided we're not doing mfg defaults)
        //
        if (!MfgDefaults) {
          if (IfrOneOfOption->Flags & EFI_IFR_FLAG_DEFAULT) {
            Status = SetVariableValue (
                      SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
                      SavedParseEntry->VarStoreName1, // name of variable store to write
                      CachedVarOffset,                // offset into variable store
                      CachedVarSize,                  // variable data size
                      &IfrOneOfOption->Value
                      );
            //
            // variable value
            //
          }
        } else {
          if (IfrOneOfOption->Flags & EFI_IFR_FLAG_MANUFACTURING) {
            Status = SetVariableValue (
                      SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
                      SavedParseEntry->VarStoreName1, // name of variable store to write
                      CachedVarOffset,                // offset into variable store
                      CachedVarSize,                  // variable data size
                      &IfrOneOfOption->Value
                      );
            //
            // variable value
            //
          }
        }
      }
    } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_CHECKBOX_OP) {
      //
      // If we're saving defaults, and the default flag is set, or we're saving
      // manufacturing defaults and the manufacturing flag is set, then save a 1.
      // By default the varstore buffer is cleared, so we don't need to save a 0 ever.
      //
      IfrCheckBox = (EFI_IFR_CHECK_BOX *) Context->CurrentIfr->RawIfrHeader;
      if (((MfgDefaults == 0) && (IfrCheckBox->Flags & EFI_IFR_FLAG_DEFAULT)) ||
          ((MfgDefaults != 0) && (IfrCheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING))
          ) {
        Size = 1;
        Status = SetVariableValue (
                  Context->CurrentIfr->VarStoreGuid1, // GUID of variable store to write
                  Context->CurrentIfr->VarStoreName1, // name of variable store to write
                  IfrCheckBox->QuestionId,            // offset into variable store
                  IfrCheckBox->Width,                 // variable data size
                  (void *) &Size
                  );
        //
        // variable value
        //
      }
    } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_NUMERIC_OP) {
      IfrNumeric = (EFI_IFR_NUMERIC *) Context->CurrentIfr->RawIfrHeader;
      Status = SetVariableValue (
                Context->CurrentIfr->VarStoreGuid1, // GUID of variable store to write
                Context->CurrentIfr->VarStoreName1, // name of variable store to write
                IfrNumeric->QuestionId,             // offset into variable store
                IfrNumeric->Width,                  // variable data size
                (void *) &IfrNumeric->Default
                );
      //
      // variable value
      //
    }

    Context->CurrentIfr = Context->CurrentIfr->Next;
  }

  return STATUS_SUCCESS;
}

static
STATUS
CreateVarStore (
  EFI_GUID  *VarGuid,
  CHAR8     *VarName,
  int       VarStoreSize
  )
/*++

Routine Description:

  Given a variable GUID.Name and the size of the variable store, allocate
  storage for maintaining the variable value.
  
Arguments:

  VarGuid - GUID for a variable
  VarName - Name of the variable
  VarStoreSize - size of the variable store

Returns:

  STATUS_ERROR   - problem with storage allocation 
  STATUS_SUCCESS - function executed successfully
 
--*/
{
  VARIABLE_STORE_ENTRY  *Entry;

  VARIABLE_STORE_ENTRY  *TempEntry;
  int                   PackSize;
  int                   VarNameLen;
  //
  // If the variable store size is zero, then do nothing. This could be valid
  // if variable steering is used in the IFR such that FormsetGUID."Setup" variable
  // store is never used.
  //
  // OPEN: What about a form that only has a time/date question? Then if some other
  // function called SetDefaults(), attempting to set time/date would result in an
  // error in the SetVarValue() function.
  //
   if (VarStoreSize == 0) {
    return STATUS_SUCCESS;
   }
  //
  // Go through our list of variable stores and see if we've already created one
  // for this Guid.Name. If so, check the size and return. Otherwise create
  // one and add it to the list.
  //
  for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) {
    if (memcmp (VarGuid, &Entry->VarPack->VariableGuid, sizeof (EFI_GUID)) == 0) {
      if (strcmp (VarName, Entry->VarName) == 0) {
        //
        // Already have one. Check size.
        //
        if (Entry->VarBufferSize != VarStoreSize) {
          Error (NULL, 0, 0, "mismatched variable store size between two formsets", VarName);
          return STATUS_ERROR;
        }

        return STATUS_SUCCESS;
      }
    }
  }
  //
  // Create a new one.
  //
  Entry = (VARIABLE_STORE_ENTRY *) malloc (sizeof (VARIABLE_STORE_ENTRY));
  if (Entry == NULL) {
    Error (NULL, 0, 0, "memory allocation failure", NULL);
    return STATUS_ERROR;
  }

  memset ((void *) Entry, 0, sizeof (VARIABLE_STORE_ENTRY));
  //
  // Compute size of the varpack
  //
  VarNameLen      = strlen (VarName) + 1;
  PackSize        = sizeof (EFI_HII_VARIABLE_PACK) + VarNameLen * sizeof (CHAR16) + VarStoreSize;
  Entry->VarPack  = (EFI_HII_VARIABLE_PACK *) malloc (PackSize);
  if (Entry->VarPack == NULL) {
    Error (NULL, 0, 0, "memory allocation failure", NULL);
    free (Entry);
    return STATUS_ERROR;
  }

  Entry->VarPack->Header.Length       = PackSize;
  Entry->VarPack->Header.Type         = EFI_HII_VARIABLE;
  Entry->VarPack->VariableNameLength  = VarNameLen * sizeof (CHAR16);
  Entry->VarName[MAX_VARIABLE_NAME - 1] = 0;
  strncpy (Entry->VarName, VarName, MAX_VARIABLE_NAME - 1);
#ifdef USE_VC8
  swprintf ((CHAR16 *) (Entry->VarPack + 1), (strlen (VarName) + 1) * sizeof (CHAR16), L"%S", VarName);
#else
  swprintf ((CHAR16 *) (Entry->VarPack + 1), L"%S", VarName);
#endif
  memcpy (&Entry->VarPack->VariableGuid, VarGuid, sizeof (EFI_GUID));
  //
  // Point VarBuffer into the allocated buffer (for convenience)
  //
  Entry->VarBuffer = (char *) Entry->VarPack + sizeof (EFI_HII_VARIABLE_PACK) + VarNameLen * sizeof (CHAR16);
  memset ((void *) Entry->VarBuffer, 0, VarStoreSize);
  Entry->VarBufferSize = VarStoreSize;
  //
  // Add this new varstore to our list
  //
  if (mVariableStores == NULL) {
    mVariableStores = Entry;
  } else {
    for (TempEntry = mVariableStores; TempEntry->Next != NULL; TempEntry = TempEntry->Next)
      ;
    TempEntry->Next = Entry;
  }
  return STATUS_SUCCESS;
}

/******************************************************************************/

/*++

Routine Description:

  The following IfrParseXX() functions are used to parse an IFR opcode numbered
  XX via a dispatch table. 
  
Arguments:

  Context - IFR parsing context into which pertinent data for the 
            current opcode can be saved. Context->LastIfr->RawIfrHeader points to 
            the raw IFR bytes currently being parsed.

Returns:

  STATUS_SUCCESS  - always
  
--*/

/*******************************************************************************/
static
STATUS
IfrParse01 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse02 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse03 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}
//
// Parse the IFR EFI_IFR_ONE_OF opcode.
//
static
STATUS
IfrParse05 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse06 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse07 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse08 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse09 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse0A (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse0B (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse0C (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse0D (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse0E (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  EFI_IFR_FORM_SET  *Op;
  Op  = (EFI_IFR_FORM_SET *) Context->LastIfr->RawIfrHeader;
  Context->LastIfr->VarStoreGuid1 = &Op->Guid;
  Context->LastIfr->VarStoreName1 = "Setup";
  Context->FormsetGuid            = &Op->Guid;
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse0F (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse10 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse11 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse12 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse13 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse14 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse15 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse16 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse17 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse18 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse19 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse1A (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse1B (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse1C (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse1D (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse1E (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse1F (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse20 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse21 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse22 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}

static
STATUS
IfrParse23 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}
//
// EFI_IFR_VARSTORE
//
static
STATUS
IfrParse24 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  EFI_IFR_VARSTORE  *Op;
  Op = (EFI_IFR_VARSTORE *) Context->LastIfr->RawIfrHeader;
  return STATUS_SUCCESS;
}
//
// VARSTORE_SELECT
//
static
STATUS
IfrParse25 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  STATUS                  Status;
  EFI_IFR_VARSTORE_SELECT *Op;
  Op      = (EFI_IFR_VARSTORE_SELECT *) Context->LastIfr->RawIfrHeader;
  Status  = GetVarStoreInfo (Context, Op->VarId, &Context->LastIfr->VarStoreGuid1, &Context->LastIfr->VarStoreName1);
  //
  // VARSTORE_SELECT sets both
  //
  Context->LastIfr->VarStoreGuid2 = Context->LastIfr->VarStoreGuid1;
  Context->LastIfr->VarStoreName2 = Context->LastIfr->VarStoreName1;
  return Status;
}
//
// VARSTORE_SELECT_PAIR
//
static
STATUS
IfrParse26 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  STATUS                        Status;
  EFI_IFR_VARSTORE_SELECT_PAIR  *Op;

  Op      = (EFI_IFR_VARSTORE_SELECT_PAIR *) Context->LastIfr->RawIfrHeader;
  Status  = GetVarStoreInfo (Context, Op->VarId, &Context->LastIfr->VarStoreGuid1, &Context->LastIfr->VarStoreName1);
  Status = GetVarStoreInfo (
            Context,
            Op->SecondaryVarId,
            &Context->LastIfr->VarStoreGuid2,
            &Context->LastIfr->VarStoreName2
            );
  return Status;
}
//
// TRUE
//
static
STATUS
IfrParse27 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}
//
// FALSe
//
static
STATUS
IfrParse28 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}
static
STATUS
IfrParse29 (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}
static
STATUS
IfrParse2A (
  IFR_PARSE_CONTEXT *Context
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  Context - GC_TODO: add argument description

Returns:

  GC_TODO: add return values

--*/
{
  return STATUS_SUCCESS;
}
