Beispiel #1
1
/**
  This function invokes Boot Manager. If all devices have not a chance to be connected,
  the connect all will be triggered. It then enumerate all boot options. If 
  a boot option from the Boot Manager page is selected, Boot Manager will boot
  from this boot option.
  
**/
VOID
UpdateBootManager (
  VOID
  )
{
  UINTN                         Index;
  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;
  UINTN                         BootOptionCount;
  EFI_STRING_ID                 Token;
  CHAR16                        *HelpString;
  EFI_STRING_ID                 HelpToken;
  UINT16                        *TempStr;
  EFI_HII_HANDLE                HiiHandle;
  UINTN                         TempSize;
  VOID                          *StartOpCodeHandle;
  VOID                          *EndOpCodeHandle;
  EFI_IFR_GUID_LABEL            *StartLabel;
  EFI_IFR_GUID_LABEL            *EndLabel;
  UINT16                        DeviceType;
  BOOLEAN                       IsLegacyOption;
  BOOLEAN                       NeedEndOp;
  UINTN                         MaxLen;

  DeviceType = (UINT16) -1;

  EfiBootManagerConnectAll ();

  //
  // for better user experience
  // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option
  // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option
  //
  EfiBootManagerRefreshAllBootOption ();

  //
  // BdsDxe doesn't group the legacy boot options for the same device type
  // It's UI's choice.
  //
  GroupMultipleLegacyBootOption4SameType ();

  BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);

  HiiHandle = gBootManagerPrivate.HiiHandle;

  //
  // Allocate space for creation of UpdateData Buffer
  //
  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  ASSERT (StartOpCodeHandle != NULL);

  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  ASSERT (EndOpCodeHandle != NULL);

  //
  // Create Hii Extend Label OpCode as the start opcode
  //
  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  StartLabel->Number       = LABEL_BOOT_OPTION;

  //
  // Create Hii Extend Label OpCode as the end opcode
  //
  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  EndLabel->Number       = LABEL_BOOT_OPTION_END;
  mKeyInput = 0;
  NeedEndOp = FALSE;
  for (Index = 0; Index < BootOptionCount; Index++) {
    //
    // At this stage we are creating a menu entry, thus the Keys are reproduceable
    //
    mKeyInput++;

    //
    // Don't display the hidden/inactive boot option
    //
    if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
      continue;
    }

    //
    // Group the legacy boot option in the sub title created dynamically
    //
    IsLegacyOption = (BOOLEAN) (
                       (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&
                       (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)
                       );

    if (!IsLegacyOption && NeedEndOp) {
      NeedEndOp = FALSE;
      HiiCreateEndOpCode (StartOpCodeHandle);
    }
    
    if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {
      if (NeedEndOp) {
        HiiCreateEndOpCode (StartOpCodeHandle);
      }

      DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType;
      Token      = HiiSetString (
                     HiiHandle,
                     0,
                     mDeviceTypeStr[
                       MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1)
                       ],
                     NULL
                     );
      HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
      NeedEndOp = TRUE;
    }

    ASSERT (BootOption[Index].Description != NULL);

    Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL);

    TempStr = BmDevicePathToStr (BootOption[Index].FilePath);
    TempSize = StrSize (TempStr);
    HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
    MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof(CHAR16);
    ASSERT (HelpString != NULL);
    StrCatS (HelpString, MaxLen, L"Device Path : ");
    StrCatS (HelpString, MaxLen, TempStr);

    HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);

    HiiCreateActionOpCode (
      StartOpCodeHandle,
      mKeyInput,
      Token,
      HelpToken,
      EFI_IFR_FLAG_CALLBACK,
      0
      );
  }

  if (NeedEndOp) {
    HiiCreateEndOpCode (StartOpCodeHandle);
  }

  HiiUpdateForm (
    HiiHandle,
    &mBootManagerGuid,
    BOOT_MANAGER_FORM_ID,
    StartOpCodeHandle,
    EndOpCodeHandle
    );

  HiiFreeOpCodeHandle (StartOpCodeHandle);
  HiiFreeOpCodeHandle (EndOpCodeHandle);

  EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
}
Beispiel #2
0
/**
  Create a Hii Update data Handle used to call IfrLibUpdateForm.

  @param ThunkContext         The HII Thunk Context.
  @param FwUpdateData         The Framework Update Data.
  @param UefiOpCodeHandle     The UEFI opcode handle.

  @retval EFI_SUCCESS       The UEFI Update Data is created successfully.
  @retval EFI_UNSUPPORTED   There is unsupported opcode in FwUpdateData.
  @retval EFI_OUT_OF_RESOURCES There is not enough resource.
**/
EFI_STATUS 
FwUpdateDataToUefiUpdateData (
  IN       HII_THUNK_CONTEXT    *ThunkContext,
  IN CONST EFI_HII_UPDATE_DATA  *FwUpdateData,
  IN       VOID                 *UefiOpCodeHandle
  )
{
  FRAMEWORK_EFI_IFR_OP_HEADER          *FwOpCode;
  FRAMEWORK_EFI_IFR_OP_HEADER          *NextFwOpCode;
  UINTN                                Index;
  UINTN                                DataCount;
  UINT8                                *OpCodeBuffer;
  LIST_ENTRY                           *StorageList;
  FORMSET_STORAGE                      *Storage;
  FORM_BROWSER_FORMSET                 *FormSet;
  CHAR16                               *DefaultVarStoreName;
  UINT16                               DefaultVarStoreId;
  EFI_IFR_VARSTORE_SELECT              *SelectVarOp;

  FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data;

  FormSet = ThunkContext->FormSet;
  DefaultVarStoreId   = FormSet->DefaultVarStoreId;
  DefaultVarStoreName = FormSet->OriginalDefaultVarStoreName;

  for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) {
    switch (FwOpCode->OpCode) {
      case FRAMEWORK_EFI_IFR_SUBTITLE_OP:
        OpCodeBuffer = HiiCreateSubTitleOpCode (UefiOpCodeHandle, ((FRAMEWORK_EFI_IFR_SUBTITLE  *) FwOpCode)->SubTitle, 0, 0, 0);
        DataCount = 1;
        break;
        
      case FRAMEWORK_EFI_IFR_TEXT_OP:
        OpCodeBuffer = F2UCreateTextOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_TEXT  *) FwOpCode);  
        DataCount = 1;
        break;

      case FRAMEWORK_EFI_IFR_REF_OP:
        OpCodeBuffer = F2UCreateReferenceOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_REF *) FwOpCode);  
        DataCount = 1;
        break;
        
      case FRAMEWORK_EFI_IFR_ONE_OF_OP:
        OpCodeBuffer = F2UCreateOneOfOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, &NextFwOpCode, &DataCount);
        if (OpCodeBuffer != NULL) {
          FwOpCode = NextFwOpCode;
          //
          // FwOpCode is already updated to point to the next opcode.
          //
          continue;
        }
        break;

      case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP:
        OpCodeBuffer = F2UCreateOrderedListOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, &NextFwOpCode, &DataCount);
        if (OpCodeBuffer != NULL) {
          FwOpCode = NextFwOpCode;
          //
          // FwOpCode is already updated to point to the next opcode.
          //
          continue;
        }
        break;
        
      case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
        OpCodeBuffer = F2UCreateCheckBoxOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode);  
        DataCount = 1;
        break;

      case FRAMEWORK_EFI_IFR_STRING_OP:
        OpCodeBuffer = F2UCreateStringOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode);  
        DataCount = 1;
        break;

      case EFI_IFR_BANNER_OP:
        OpCodeBuffer = F2UCreateBannerOpCode (UefiOpCodeHandle, (EFI_IFR_BANNER *) FwOpCode);  
        DataCount = 1;
        break;

      case EFI_IFR_END_ONE_OF_OP:
        OpCodeBuffer = HiiCreateEndOpCode (UefiOpCodeHandle);
        DataCount = 1;
        break;

      case FRAMEWORK_EFI_IFR_NUMERIC_OP:
        OpCodeBuffer = F2UCreateNumericOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode);
        DataCount = 1;
        break;
      
      case EFI_IFR_VARSTORE_SELECT_OP:
        OpCodeBuffer = (UINT8 *) FwOpCode;
        SelectVarOp  = (EFI_IFR_VARSTORE_SELECT *) FwOpCode;
        //
        // Check whether the selected VarId is in StorageList.
        //
        StorageList = GetFirstNode (&FormSet->StorageListHead);
        while (!IsNull (&FormSet->StorageListHead, StorageList)) {
          Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
          if (Storage->VarStoreId == SelectVarOp->VarId) {
            break;
          }
          StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
        }
        ASSERT (!IsNull (&FormSet->StorageListHead, StorageList));
        //
        // Change VarStoreId to the selected VarId.
        //
        FormSet->DefaultVarStoreId = SelectVarOp->VarId;
        if (SelectVarOp->VarId == DefaultVarStoreId)  {
          FormSet->OriginalDefaultVarStoreName = DefaultVarStoreName;
        }
        DataCount = 1;
        break;

      default:
        ASSERT (FALSE);
        return EFI_UNSUPPORTED;
    }

    if (OpCodeBuffer == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length);
  }

  //
  // Revert FromSet default varstore ID.
  //
  FormSet->DefaultVarStoreId           = DefaultVarStoreId;
  FormSet->OriginalDefaultVarStoreName = DefaultVarStoreName;
  return EFI_SUCCESS;
}
Beispiel #3
0
/**
  Create UEFI HII Numeric Opcode from a Framework HII Numeric Opcode.

  @param UefiUpdateDataHandle    The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
  @param ThunkContext            The HII Thunk Context.
  @param FwOpcode                The input Framework Opcode.

  @retval NULL   There is not enough space left in Buffer to add the opcode.
  @retval Other  A pointer to the created opcode.
  
**/
UINT8 *
F2UCreateNumericOpCode (
  IN OUT   VOID                        *UefiUpdateDataHandle,
  IN       HII_THUNK_CONTEXT           *ThunkContext,
  IN CONST FRAMEWORK_EFI_IFR_NUMERIC   *FwOpcode
  )
{
  EFI_STATUS      Status;
  EFI_IFR_NUMERIC UOpcode;
  EFI_IFR_DEFAULT UOpcodeDefault;
  UINT8           *NumbericOpCode;
  UINT8           *OpcodeBuffer;

  ZeroMem (&UOpcode, sizeof(UOpcode));

  if (FwOpcode->Key == 0) {
    Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    if (EFI_ERROR (Status)) {
      //
      // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
      //
      UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    }
  } else {
    UOpcode.Question.QuestionId    = FwOpcode->Key;
  }

  UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
  UOpcode.Header.OpCode = EFI_IFR_NUMERIC_OP;
  //
  // We need to create a nested default value for the UEFI Numeric Opcode.
  // So turn on the scope.
  //
  UOpcode.Header.Scope = 1;

  UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
  UOpcode.Question.Header.Help = FwOpcode->Help;

  UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;
  UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;

  UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));

  //
  // Framework Numeric values are all in UINT16 and displayed as decimal.
  //
  UOpcode.data.u16.MinValue = FwOpcode->Minimum;
  UOpcode.data.u16.MaxValue = FwOpcode->Maximum;
  UOpcode.data.u16.Step = FwOpcode->Step;

  switch (FwOpcode->Width) {
    case 1: 
    {
      UOpcode.Flags           =  EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC; 
      break;
    } 
    case 2: 
    {
      UOpcode.Flags           =  EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC; 
      break;
    }
    default: 
    {
      ASSERT (FALSE);
      return NULL;
    }
  }
  
  NumbericOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
  if (NumbericOpCode == NULL) {
    return NULL;
  }

  //
  // We need to create a default value.
  //
  ZeroMem (&UOpcodeDefault, sizeof (UOpcodeDefault));
  UOpcodeDefault.Header.Length = (UINT8) sizeof (UOpcodeDefault);
  UOpcodeDefault.Header.OpCode = EFI_IFR_DEFAULT_OP;

  UOpcodeDefault.DefaultId = 0;

  switch (FwOpcode->Width) {
    case 1: 
    {
      UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_8;
      break;
    } 
    case 2: 
    {
      UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_16;
      break;
    }
  }

  CopyMem (&UOpcodeDefault.Value.u8, &FwOpcode->Default, FwOpcode->Width);

  OpcodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcodeDefault, sizeof(UOpcodeDefault));
  if (OpcodeBuffer == NULL) {
    return NULL;
  }

  OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);
  if (OpcodeBuffer == NULL) {
    return NULL;
  }

  return NumbericOpCode;
}
Beispiel #4
0
/**
  Create UEFI HII "Ordered List" Opcode from a Framework HII "Ordered List" Opcode.

  @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
  @param ThunkContext         The HII Thunk Context.
  @param FwOpcode             The input Framework Opcode.
  @param NextFwOpcode         Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of
                              the "Ordered List".
  @param OpcodeCount          The number of Opcode for the complete Framework "Ordered List" Opcode.
                      
  @retval NULL   There is not enough space left in Buffer to add the opcode.
  @retval Other  A pointer to the created opcode.
  
**/
UINT8 *
F2UCreateOrderedListOpCode (
  IN OUT    VOID                          *UefiUpdateDataHandle,
  IN       HII_THUNK_CONTEXT              *ThunkContext,
  IN CONST FRAMEWORK_EFI_IFR_ORDERED_LIST *FwOpcode,
  OUT      FRAMEWORK_EFI_IFR_OP_HEADER    **NextFwOpcode,
  OUT      UINTN                          *OpcodeCount
  )
{
  EFI_IFR_ORDERED_LIST              UOpcode;
  EFI_STATUS                        Status;
  FRAMEWORK_EFI_IFR_OP_HEADER       *FwOpHeader;
  FRAMEWORK_EFI_IFR_ONE_OF_OPTION   *FwOneOfOp;
  UINT8                             *OpcodeBuffer;   
  UINT8                             *OrderListOpCode;

  ZeroMem (&UOpcode, sizeof(UOpcode));
  *OpcodeCount = 0;

  UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
  UOpcode.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
  UOpcode.Header.Scope  = 1;

  UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
  UOpcode.Question.Header.Help = FwOpcode->Help;
  UOpcode.Question.VarStoreId  = ThunkContext->FormSet->DefaultVarStoreId;
  UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;

  UOpcode.MaxContainers = FwOpcode->MaxEntries;

  //
  // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
  //
  FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
  while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
    
    FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
    if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) {
      UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
      
      if (UOpcode.Question.QuestionId == 0) {
        Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
        if (EFI_ERROR (Status)) {
          UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);
        }

      }
    }

    if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) ==  EFI_IFR_FLAG_RESET_REQUIRED) {
      UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
    }

    FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
  }

  if (UOpcode.Question.QuestionId == 0) {
    Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    if (EFI_ERROR (Status)) {
      UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    }
  }
 
  OrderListOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
  if (OrderListOpCode == NULL) {
    return NULL;
  }
  *OpcodeCount += 1;

  FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
  while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    //
    // Each entry of Order List in Framework HII is always 1 byte in size
    //
    OpcodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, 1);
    if (OpcodeBuffer == NULL) {
      return NULL;
    }
    FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
    *OpcodeCount += 1;
  }

  OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);
  if (OpcodeBuffer != NULL) {
    *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
    *OpcodeCount += 1;
  }

  return OrderListOpCode;
}
Beispiel #5
0
/**
  Create UEFI HII "One Of" Opcode from a Framework HII "One Of" Opcode.

  @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
  @param ThunkContext             The HII Thunk Context.
  @param FwOpcode                 The input Framework Opcode.
  @param NextFwOpcode             Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of
                                  the "One Of Option".
  @param OpcodeCount              The number of Opcode for the complete Framework "One Of" Opcode.
                      
  @retval NULL   There is not enough space left in Buffer to add the opcode.
  @retval Other  A pointer to the created opcode.
  
**/
UINT8 *
F2UCreateOneOfOpCode (
  IN OUT   VOID                        *UefiUpdateDataHandle,
  IN       HII_THUNK_CONTEXT           *ThunkContext,
  IN CONST FRAMEWORK_EFI_IFR_ONE_OF    *FwOpcode,
  OUT      FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,
  OUT      UINTN                       *OpcodeCount
  )
{
  EFI_STATUS                          Status;
  EFI_IFR_ONE_OF                      UOpcode;
  FRAMEWORK_EFI_IFR_OP_HEADER         *FwOpHeader;
  FRAMEWORK_EFI_IFR_ONE_OF_OPTION     *FwOneOfOp;
  UINT8                               *OpCodeBuffer;
  UINT8                               *OneOfOpCodeBuffer;

  ASSERT (NextFwOpcode != NULL);
  ASSERT (OpcodeCount != NULL);

  ZeroMem (&UOpcode, sizeof(UOpcode));
  *OpcodeCount = 0;

  UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
  UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OP;
  UOpcode.Header.Scope  = 1;

  UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
  UOpcode.Question.Header.Help = FwOpcode->Help;
  UOpcode.Question.VarStoreId  = ThunkContext->FormSet->DefaultVarStoreId;
  UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
  
  //
  // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
  //
  FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
  while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
    
    FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
    if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) {
      UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
      
      if (UOpcode.Question.QuestionId == 0) {
        Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
        if (EFI_ERROR (Status)) {
          UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);
        }
      }

    }

    if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {
      UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
    }

    FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
  }


  if (UOpcode.Question.QuestionId == 0) {
    //
    // Assign QuestionId if still not assigned.
    //
    Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    if (EFI_ERROR (Status)) {
      UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    }
  }
  
  OneOfOpCodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof (UOpcode));
  if (OneOfOpCodeBuffer == NULL) {
    return NULL;
  }
  *OpcodeCount += 1;

  //
  // Go over again the Framework IFR binary to build the UEFI One Of Option opcodes.
  //
  FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
  while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {

    FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
      
    OpCodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, FwOpcode->Width);
    if (OpCodeBuffer == NULL) {
      return NULL;
    }

    OpCodeBuffer = CreateGuidOptionKeyOpCode (UefiUpdateDataHandle, UOpcode.Question.QuestionId, FwOneOfOp->Value, FwOneOfOp->Key);
    if (OpCodeBuffer == NULL) {
      return NULL;
    }

    FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
    *OpcodeCount += 1;
  }

  OpCodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);
  if (OpCodeBuffer != NULL) {
    *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
    *OpcodeCount += 1;
  }

  return OneOfOpCodeBuffer;
}
Beispiel #6
0
/**
  This function invokes Boot Manager. If all devices have not a chance to be connected,
  the connect all will be triggered. It then enumerate all boot options. If
  a boot option from the Boot Manager page is selected, Boot Manager will boot
  from this boot option.

**/
VOID
CallBootManager (
    VOID
)
{
    EFI_STATUS                  Status;
    BDS_COMMON_OPTION           *Option;
    LIST_ENTRY                  *Link;
    CHAR16                      *ExitData;
    UINTN                       ExitDataSize;
    EFI_STRING_ID               Token;
    EFI_INPUT_KEY               Key;
    CHAR16                      *HelpString;
    UINTN                       HelpSize;
    EFI_STRING_ID               HelpToken;
    UINT16                      *TempStr;
    EFI_HII_HANDLE              HiiHandle;
    EFI_BROWSER_ACTION_REQUEST  ActionRequest;
    VOID                        *StartOpCodeHandle;
    VOID                        *EndOpCodeHandle;
    EFI_IFR_GUID_LABEL          *StartLabel;
    EFI_IFR_GUID_LABEL          *EndLabel;
    UINT16                      DeviceType;
    BOOLEAN                     IsLegacyOption;
    BOOLEAN                     NeedEndOp;

    DeviceType = (UINT16) -1;
    gOption    = NULL;
    InitializeListHead (&mBootOptionsList);

    //
    // Connect all prior to entering the platform setup menu.
    //
    if (!gConnectAllHappened) {
        BdsLibConnectAllDriversToAllControllers ();
        gConnectAllHappened = TRUE;
    }

    BdsLibEnumerateAllBootOption (&mBootOptionsList);

    //
    // Group the legacy boot options for the same device type
    //
    GroupMultipleLegacyBootOption4SameType ();

    InitializeListHead (&mBootOptionsList);
    BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder");

    HiiHandle = gBootManagerPrivate.HiiHandle;

    //
    // Allocate space for creation of UpdateData Buffer
    //
    StartOpCodeHandle = HiiAllocateOpCodeHandle ();
    ASSERT (StartOpCodeHandle != NULL);

    EndOpCodeHandle = HiiAllocateOpCodeHandle ();
    ASSERT (EndOpCodeHandle != NULL);

    //
    // Create Hii Extend Label OpCode as the start opcode
    //
    StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
    StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
    StartLabel->Number       = LABEL_BOOT_OPTION;

    //
    // Create Hii Extend Label OpCode as the end opcode
    //
    EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
    EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
    EndLabel->Number       = LABEL_BOOT_OPTION_END;

    mKeyInput = 0;
    NeedEndOp = FALSE;
    for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
        Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);

        //
        // At this stage we are creating a menu entry, thus the Keys are reproduceable
        //
        mKeyInput++;

        //
        // Don't display the hidden/inactive boot option
        //
        if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) {
            continue;
        }

        //
        // Group the legacy boot option in the sub title created dynamically
        //
        IsLegacyOption = (BOOLEAN) (
                             (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&
                             (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)
                         );

        if (!IsLegacyOption && NeedEndOp) {
            NeedEndOp = FALSE;
            HiiCreateEndOpCode (StartOpCodeHandle);
        }

        if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) {
            if (NeedEndOp) {
                HiiCreateEndOpCode (StartOpCodeHandle);
            }

            DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType;
            Token      = HiiSetString (
                             HiiHandle,
                             0,
                             mDeviceTypeStr[
                                 MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1)
                             ],
                             NULL
                         );
            HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
            NeedEndOp = TRUE;
        }

        ASSERT (Option->Description != NULL);

        Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);

        TempStr = DevicePathToStr (Option->DevicePath);
        HelpSize = StrSize (TempStr) + StrSize (L"Device Path : ");
        HelpString = AllocateZeroPool (HelpSize);
        ASSERT (HelpString != NULL);
        StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : ");
        StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr);

        HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);

        HiiCreateActionOpCode (
            StartOpCodeHandle,
            mKeyInput,
            Token,
            HelpToken,
            EFI_IFR_FLAG_CALLBACK,
            0
        );
    }

    if (NeedEndOp) {
        HiiCreateEndOpCode (StartOpCodeHandle);
    }

    HiiUpdateForm (
        HiiHandle,
        &gBootManagerFormSetGuid,
        BOOT_MANAGER_FORM_ID,
        StartOpCodeHandle,
        EndOpCodeHandle
    );

    HiiFreeOpCodeHandle (StartOpCodeHandle);
    HiiFreeOpCodeHandle (EndOpCodeHandle);

    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
    Status = gFormBrowser2->SendForm (
                 gFormBrowser2,
                 &HiiHandle,
                 1,
                 &gBootManagerFormSetGuid,
                 0,
                 NULL,
                 &ActionRequest
             );
    if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
        EnableResetRequired ();
    }

    if (gOption == NULL) {
        return ;
    }

    //
    // Will leave browser, check any reset required change is applied? if yes, reset system
    //
    SetupResetReminder ();

    //
    // Restore to original mode before launching boot option.
    //
    BdsSetConsoleMode (FALSE);

    //
    // parse the selected option
    //
    Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);

    if (!EFI_ERROR (Status)) {
        gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
        PlatformBdsBootSuccess (gOption);
    } else {
        gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
        PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
        gST->ConOut->OutputString (
            gST->ConOut,
            GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
        );
        gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
    }
}
Beispiel #7
0
/**
  Create a Hii Update data Handle used to call IfrLibUpdateForm.

  @param ThunkContext         The HII Thunk Context.
  @param FwUpdateData         The Framework Update Data.
  @param UefiOpCodeHandle     The UEFI opcode hanlde.

  @retval EFI_SUCCESS       The UEFI Update Data is created successfully.
  @retval EFI_UNSUPPORTED   There is unsupported opcode in FwUpdateData.
  @retval EFI_OUT_OF_RESOURCES There is not enough resource.
**/
EFI_STATUS 
FwUpdateDataToUefiUpdateData (
  IN       HII_THUNK_CONTEXT    *ThunkContext,
  IN CONST EFI_HII_UPDATE_DATA  *FwUpdateData,
  IN       VOID                 *UefiOpCodeHandle
  )
{
  FRAMEWORK_EFI_IFR_OP_HEADER          *FwOpCode;
  FRAMEWORK_EFI_IFR_OP_HEADER          *NextFwOpCode;
  UINTN                                Index;
  UINTN                                DataCount;
  UINT8                                *OpCodeBuffer;

  FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data;

  for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) {
    switch (FwOpCode->OpCode) {
      case FRAMEWORK_EFI_IFR_SUBTITLE_OP:
        OpCodeBuffer = HiiCreateSubTitleOpCode (UefiOpCodeHandle, ((FRAMEWORK_EFI_IFR_SUBTITLE  *) FwOpCode)->SubTitle, 0, 0, 0);
        DataCount = 1;
        break;
        
      case FRAMEWORK_EFI_IFR_TEXT_OP:
        OpCodeBuffer = F2UCreateTextOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_TEXT  *) FwOpCode);  
        DataCount = 1;
        break;

      case FRAMEWORK_EFI_IFR_REF_OP:
        OpCodeBuffer = F2UCreateReferenceOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_REF *) FwOpCode);  
        DataCount = 1;
        break;
        
      case FRAMEWORK_EFI_IFR_ONE_OF_OP:
        OpCodeBuffer = F2UCreateOneOfOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, &NextFwOpCode, &DataCount);
        if (OpCodeBuffer != NULL) {
          FwOpCode = NextFwOpCode;
          //
          // FwOpCode is already updated to point to the next opcode.
          //
          continue;
        }
        break;

      case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP:
        OpCodeBuffer = F2UCreateOrderedListOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, &NextFwOpCode, &DataCount);
        if (OpCodeBuffer != NULL) {
          FwOpCode = NextFwOpCode;
          //
          // FwOpCode is already updated to point to the next opcode.
          //
          continue;
        }
        break;
        
      case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
        OpCodeBuffer = F2UCreateCheckBoxOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode);  
        DataCount = 1;
        break;

      case FRAMEWORK_EFI_IFR_STRING_OP:
        OpCodeBuffer = F2UCreateStringOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode);  
        DataCount = 1;
        break;

      case EFI_IFR_BANNER_OP:
        OpCodeBuffer = F2UCreateBannerOpCode (UefiOpCodeHandle, (EFI_IFR_BANNER *) FwOpCode);  
        DataCount = 1;
        break;

      case EFI_IFR_END_ONE_OF_OP:
        OpCodeBuffer = HiiCreateEndOpCode (UefiOpCodeHandle);
        DataCount = 1;
        break;

      case FRAMEWORK_EFI_IFR_NUMERIC_OP:
        OpCodeBuffer = F2UCreateNumericOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode);
        DataCount = 1;
        break;

      default:
        ASSERT (FALSE);
        return EFI_UNSUPPORTED;
    }

    if (OpCodeBuffer == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length);
  }

  return EFI_SUCCESS;
}