/** Find Esrt Entry stored in ESRT repository. @param[in] FwClass Firmware class guid in Esrt entry @param[in] Attribute Esrt from Non FMP or FMP instance @param[out] Entry Esrt entry returned @retval EFI_SUCCESS Successfully find an Esrt entry @retval EF_NOT_FOUND No Esrt entry found **/ EFI_STATUS GetEsrtEntry ( IN EFI_GUID *FwClass, IN UINTN Attribute, OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry ) { EFI_STATUS Status; CHAR16 *VariableName; EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository; UINTN RepositorySize; UINTN Index; UINTN EsrtNum; EsrtRepository = NULL; // // Get Esrt index buffer // if (Attribute == ESRT_FROM_FMP) { VariableName = EFI_ESRT_FMP_VARIABLE_NAME; } else { VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME; } Status = GetVariable2 ( VariableName, &gEfiCallerIdGuid, (VOID **) &EsrtRepository, &RepositorySize ); if (EFI_ERROR(Status)) { goto EXIT; } if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) { DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n")); Status = EFI_ABORTED; goto EXIT; } Status = EFI_NOT_FOUND; EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY); for (Index = 0; Index < EsrtNum; Index++) { if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) { CopyMem(Entry, &EsrtRepository[Index], sizeof(EFI_SYSTEM_RESOURCE_ENTRY)); Status = EFI_SUCCESS; break; } } EXIT: if (EsrtRepository != NULL) { FreePool(EsrtRepository); } return Status; }
/** Do the platform specific action before the console is connected. Such as: Update console variable; Register new Driver#### or Boot####; Signal ReadyToLock event. **/ VOID EFIAPI PlatformBootManagerBeforeConsole ( VOID ) { UINTN Index; EFI_STATUS Status; WIN_NT_SYSTEM_CONFIGURATION *Configuration; GetVariable2 (L"Setup", &gEfiWinNtSystemConfigGuid, (VOID **) &Configuration, NULL); if (Configuration != NULL) { // // SetupVariable is corrupt // Configuration->ConOutRow = PcdGet32 (PcdConOutColumn); Configuration->ConOutColumn = PcdGet32 (PcdConOutRow); Status = gRT->SetVariable ( L"Setup", &gEfiWinNtSystemConfigGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (WIN_NT_SYSTEM_CONFIGURATION), Configuration ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Failed to save Setup Variable to non-volatile storage, Status = %r\n", Status)); } FreePool (Configuration); } // // Update the ocnsole variables. // for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) { if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL); } if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL); } if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL); } } // // From PI spec vol2: // Prior to invoking any UEFI drivers, applications, or connecting consoles, // the platform should signal the event EFI_END_OF_DXE_EVENT_GUID // EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); }
/** Load and deserialize platform configuration. When the function fails, output parameters are indeterminate. @param[out] PlatformConfig The platform configuration to receive the loaded data. @param[out] OptionalElements This bitmap describes the presence of optional configuration elements that have been loaded. PLATFORM_CONFIG_F_DOWNGRADE means that some unknown elements, present in the wire format, have been ignored. @retval EFI_SUCCESS Loading & deserialization successful. @return Error codes returned by GetVariable2(). **/ EFI_STATUS EFIAPI PlatformConfigLoad ( OUT PLATFORM_CONFIG *PlatformConfig, OUT UINT64 *OptionalElements ) { VOID *Data; UINTN DataSize; EFI_STATUS Status; // // Any translation done in PlatformConfigSave() would have to be mirrored // here. For now, just load the binary dump. // // Versioning of the binary wire format is implemented based on size // (only incremental changes, ie. new fields), and on GUID. // (Incompatible changes require a GUID change.) // Status = GetVariable2 (mVariableName, &gOvmfPlatformConfigGuid, &Data, &DataSize); if (EFI_ERROR (Status)) { return Status; } *OptionalElements = 0; if (DataSize > sizeof *PlatformConfig) { // // Handle firmware downgrade -- keep only leading part. // CopyMem (PlatformConfig, Data, sizeof *PlatformConfig); *OptionalElements |= PLATFORM_CONFIG_F_DOWNGRADE; } else { CopyMem (PlatformConfig, Data, DataSize); // // Handle firmware upgrade -- zero out missing fields. // ZeroMem ((UINT8 *)PlatformConfig + DataSize, sizeof *PlatformConfig - DataSize); } // // Based on DataSize, report the optional features that we recognize. // if (DataSize >= (OFFSET_OF (PLATFORM_CONFIG, VerticalResolution) + sizeof PlatformConfig->VerticalResolution)) { *OptionalElements |= PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION; } FreePool (Data); return EFI_SUCCESS; }
/** Local worker function to obtain device path information from DebugPort variable. Records requested settings in DebugPort device structure. **/ EFI_DEVICE_PATH_PROTOCOL * GetDebugPortVariable ( VOID ) { UINTN DataSize; EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable; EFI_DEVICE_PATH_PROTOCOL *DevicePath; GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **) &DebugPortVariable, &DataSize); if (DebugPortVariable == NULL) { return NULL; } DevicePath = DebugPortVariable; while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) { DevicePath = NextDevicePathNode (DevicePath); } if (IsDevicePathEnd (DevicePath)) { FreePool (DebugPortVariable); return NULL; } else { CopyMem ( &mDebugPortDevice.BaudRate, &((UART_DEVICE_PATH *) DevicePath)->BaudRate, sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate) ); mDebugPortDevice.ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH; mDebugPortDevice.Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT; CopyMem ( &mDebugPortDevice.Parity, &((UART_DEVICE_PATH *) DevicePath)->Parity, sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity) ); CopyMem ( &mDebugPortDevice.DataBits, &((UART_DEVICE_PATH *) DevicePath)->DataBits, sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits) ); CopyMem ( &mDebugPortDevice.StopBits, &((UART_DEVICE_PATH *) DevicePath)->StopBits, sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits) ); return DebugPortVariable; } }
/** Returns the value used to fill in the LastAttemptVersion field of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() service of the Firmware Management Protocol. The value is read from a UEFI variable. If the UEFI variables does not exist, then a default last attempt version value is returned. UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion" @return The last attempt version value for the most recent capsule update. **/ UINT32 GetLastAttemptVersionFromVariable ( VOID ) { EFI_STATUS Status; UINT32 *Value; UINTN Size; UINT32 Version; Value = NULL; Size = 0; Version = DEFAULT_LASTATTEMPT; Status = GetVariable2 (VARNAME_LASTATTEMPTVERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size); if (EFI_ERROR (Status) || (Value == NULL)) { DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Version from variable. Status = %r\n", Status)); return Version; } // // No error from call // if (Size == sizeof (*Value)) { // // Successful read // Version = *Value; } else { // // Return default since size was unknown // DEBUG ( (DEBUG_ERROR, "Getting Last Attempt Version variable returned a size different than expected. Size = 0x%x\n", Size) ); } FreePool (Value); return Version; }
/** Connect the network devices. @retval EFI_SUCCESS At least one network device was connected. @retval EFI_DEVICE_ERROR Network devices were not connected due to an error. **/ EFI_STATUS ConnectNetwork ( VOID ) { EFI_STATUS Status; BOOLEAN OneConnected; EFI_DEVICE_PATH_PROTOCOL *Devices; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_DEVICE_PATH_PROTOCOL *SingleDevice; UINTN Size; OneConnected = FALSE; GetVariable2 (mNetworkDeviceList, &gEfiCallerIdGuid, (VOID **) &Devices, NULL); TempDevicePath = Devices; while (TempDevicePath != NULL) { SingleDevice = GetNextDevicePathInstance (&TempDevicePath, &Size); Status = EfiBootManagerConnectDevicePath (SingleDevice, NULL); if (!EFI_ERROR (Status)) { OneConnected = TRUE; } FreePool (SingleDevice); } if (Devices != NULL) { FreePool (Devices); } if (OneConnected) { return EFI_SUCCESS; } else { // // Cached network devices list doesn't exist or is NOT valid. // return ConnectAllAndCreateNetworkDeviceList (); } }
/** Initialize CapsuleLast variables. **/ VOID InitCapsuleLastVariable ( VOID ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; VOID *CapsuleResult; UINTN Size; CHAR16 CapsuleLastStr[sizeof("Capsule####")]; BootMode = GetBootModeHob(); if (BootMode == BOOT_ON_FLASH_UPDATE) { Status = gRT->SetVariable( L"CapsuleLast", &gEfiCapsuleReportGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL ); // Do not lock it because it will be updated later. } else { // // Check if OS/APP cleared L"Capsule####" // ZeroMem(CapsuleLastStr, sizeof(CapsuleLastStr)); Size = sizeof(L"Capsule####") - sizeof(CHAR16); // no zero terminator Status = gRT->GetVariable( L"CapsuleLast", &gEfiCapsuleReportGuid, NULL, &Size, CapsuleLastStr ); if (!EFI_ERROR(Status)) { // // L"CapsuleLast" is got, check if data is there. // Status = GetVariable2 ( CapsuleLastStr, &gEfiCapsuleReportGuid, (VOID **) &CapsuleResult, NULL ); if (EFI_ERROR(Status)) { // // If no data, delete L"CapsuleLast" // Status = gRT->SetVariable( L"CapsuleLast", &gEfiCapsuleReportGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL ); } } // Lock it in normal boot path per UEFI spec. Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock); if (!EFI_ERROR(Status)) { Status = VariableLock->RequestToLock(VariableLock, L"CapsuleLast", &gEfiCapsuleReportGuid); ASSERT_EFI_ERROR(Status); } } }
/** Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid is also updated. @param CallbackData The context data for BMM. @return EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND If L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource **/ EFI_STATUS UpdateBBSOption ( IN LEGACY_BOOT_NV_DATA *NVMapData ) { UINTN Index; UINTN Index2; UINTN CurrentType; VOID *BootOptionVar; CHAR16 VarName[100]; UINTN OptionSize; EFI_STATUS Status; UINT32 *Attribute; LEGACY_MENU_OPTION *OptionMenu; UINT16 *LegacyDev; UINT16 *InitialLegacyDev; UINT8 *VarData; UINTN VarSize; LEGACY_DEV_ORDER_ENTRY *DevOrder; UINT8 *OriginalPtr; UINT8 *DisMap; UINTN Pos; UINTN Bit; UINT16 *NewOrder; UINT16 Tmp; UINT16 *EnBootOption; UINTN EnBootOptionCount; UINT16 *DisBootOption; UINTN DisBootOptionCount; UINTN BufferSize; DisMap = NULL; NewOrder = NULL; CurrentType = 0; DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; Status = EFI_SUCCESS; // // Update the Variable "LegacyDevOrder" // GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); if (VarData == NULL) { return EFI_NOT_FOUND; } OriginalPtr = VarData; while (mBbsType[CurrentType] != BBS_UNKNOWN) { switch (mBbsType[CurrentType]) { case BBS_FLOPPY: OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu; LegacyDev = NVMapData->LegacyFD; InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; BufferSize = sizeof (NVMapData->LegacyFD); break; case BBS_HARDDISK: OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu; LegacyDev = NVMapData->LegacyHD; InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; BufferSize = sizeof (NVMapData->LegacyHD); break; case BBS_CDROM: OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu; LegacyDev = NVMapData->LegacyCD; InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; BufferSize = sizeof (NVMapData->LegacyCD); break; case BBS_EMBED_NETWORK: OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu; LegacyDev = NVMapData->LegacyNET; InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; BufferSize = sizeof (NVMapData->LegacyNET); break; default: ASSERT (mBbsType[CurrentType] == BBS_BEV_DEVICE); OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu; LegacyDev = NVMapData->LegacyBEV; InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; BufferSize = sizeof (NVMapData->LegacyBEV); break; } // // Check whether has value changed. // if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) == 0) { CurrentType++; continue; } DevOrder = (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr; while (VarData < OriginalPtr + VarSize) { if (DevOrder->BbsType == mBbsType[CurrentType]) { break; } VarData += sizeof (BBS_TYPE) + DevOrder->Length; DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; } if (VarData >= OriginalPtr + VarSize) { FreePool (OriginalPtr); return EFI_NOT_FOUND; } NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); if (NewOrder == NULL) { FreePool (OriginalPtr); return EFI_OUT_OF_RESOURCES; } for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { if (0xFF == LegacyDev[Index]) { break; } NewOrder[Index] = LegacyDev[Index]; } // // Only the enable/disable state of each boot device with same device type can be changed, // so we can count on the index information in DevOrder. // DisMap bit array is the only reliable source to check a device's en/dis state, // so we use DisMap to set en/dis state of each item in NewOrder array // for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); Pos = Tmp / 8; Bit = 7 - (Tmp % 8); if ((DisMap[Pos] & (1 << Bit)) != 0) { NewOrder[Index] = (UINT16) (0xFF00 | Tmp); Index++; } } CopyMem ( DevOrder->Data, NewOrder, DevOrder->Length - sizeof (DevOrder->Length) ); FreePool (NewOrder); // // Update BootOrder and Boot####.Attribute // // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order // ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); OrderLegacyBootOption4SameType ( DevOrder->Data, DevOrder->Length / sizeof (UINT16) - 1, &EnBootOption, &EnBootOptionCount, &DisBootOption, &DisBootOptionCount ); // // 2. Deactivate the DisBootOption and activate the EnBootOption // for (Index = 0; Index < DisBootOptionCount; Index++) { UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); if (BootOptionVar != NULL) { Attribute = (UINT32 *) BootOptionVar; *Attribute &= ~LOAD_OPTION_ACTIVE; Status = gRT->SetVariable ( VarName, &gEfiGlobalVariableGuid, VAR_FLAG, OptionSize, BootOptionVar ); FreePool (BootOptionVar); } } for (Index = 0; Index < EnBootOptionCount; Index++) { UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize); if (BootOptionVar != NULL) { Attribute = (UINT32 *) BootOptionVar; *Attribute |= LOAD_OPTION_ACTIVE; Status = gRT->SetVariable ( VarName, &gEfiGlobalVariableGuid, VAR_FLAG, OptionSize, BootOptionVar ); FreePool (BootOptionVar); } } FreePool (EnBootOption); FreePool (DisBootOption); CurrentType++; } Status = gRT->SetVariable ( VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, VarSize, OriginalPtr ); FreePool (OriginalPtr); return Status; }
/** Base on the L"LegacyDevOrder" variable to build the current order data. **/ VOID GetLegacyOptionsOrder ( VOID ) { UINTN VarSize; UINT8 *VarData; UINT8 *VarTmp; LEGACY_DEV_ORDER_ENTRY *DevOrder; UINT16 *LegacyDev; UINTN Index; LEGACY_MENU_OPTION *OptionMenu; UINT16 VarDevOrder; UINTN Pos; UINTN Bit; UINT8 *DisMap; DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap)); // // Get Device Order from variable // GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize); VarTmp = VarData; if (NULL != VarData) { DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; while (VarData < VarTmp + VarSize) { switch (DevOrder->BbsType) { case BBS_FLOPPY: LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD; OptionMenu = &LegacyFDMenu; break; case BBS_HARDDISK: LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD; OptionMenu = &LegacyHDMenu; break; case BBS_CDROM: LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD; OptionMenu = &LegacyCDMenu; break; case BBS_EMBED_NETWORK: LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET; OptionMenu = &LegacyNETMenu; break; case BBS_BEV_DEVICE: LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV; OptionMenu = &LegacyBEVMenu; break; case BBS_UNKNOWN: default: ASSERT (FALSE); DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n")); break; } // // Create oneof tag here for FD/HD/CD #1 #2 // for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16)); if (0xFF00 == (VarDevOrder & 0xFF00)) { LegacyDev[Index] = 0xFF; Pos = (VarDevOrder & 0xFF) / 8; Bit = 7 - ((VarDevOrder & 0xFF) % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); } else { LegacyDev[Index] = VarDevOrder & 0xFF; } } VarData += sizeof (BBS_TYPE); VarData += *(UINT16 *) VarData; DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; } } CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA)); }
/** Build the Boot#### or Driver#### option from the VariableName. @param VariableName Variable name of the load option @param VendorGuid Variable GUID of the load option @param Option Return the load option. @retval EFI_SUCCESS Get the option just been created @retval EFI_NOT_FOUND Failed to get the new option **/ EFI_STATUS EFIAPI EfiBootManagerVariableToLoadOptionEx ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option ) { EFI_STATUS Status; UINT32 Attribute; UINT16 FilePathSize; UINT8 *Variable; UINT8 *VariablePtr; UINTN VariableSize; EFI_DEVICE_PATH_PROTOCOL *FilePath; UINT8 *OptionalData; UINT32 OptionalDataSize; CHAR16 *Description; EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; UINT16 OptionNumber; if ((VariableName == NULL) || (Option == NULL)) { return EFI_INVALID_PARAMETER; } if (!BmIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) { return EFI_INVALID_PARAMETER; } // // Read the variable // GetVariable2 (VariableName, VendorGuid, (VOID **) &Variable, &VariableSize); if (Variable == NULL) { return EFI_NOT_FOUND; } // // Validate *#### variable data. // if (!BmValidateOption(Variable, VariableSize)) { FreePool (Variable); return EFI_INVALID_PARAMETER; } // // Get the option attribute // VariablePtr = Variable; Attribute = ReadUnaligned32 ((UINT32 *) VariablePtr); VariablePtr += sizeof (UINT32); // // Get the option's device path size // FilePathSize = ReadUnaligned16 ((UINT16 *) VariablePtr); VariablePtr += sizeof (UINT16); // // Get the option's description string // Description = (CHAR16 *) VariablePtr; // // Get the option's description string size // VariablePtr += StrSize ((CHAR16 *) VariablePtr); // // Get the option's device path // FilePath = (EFI_DEVICE_PATH_PROTOCOL *) VariablePtr; VariablePtr += FilePathSize; OptionalDataSize = (UINT32) (VariableSize - (UINTN) (VariablePtr - Variable)); if (OptionalDataSize == 0) { OptionalData = NULL; } else { OptionalData = VariablePtr; } Status = EfiBootManagerInitializeLoadOption ( Option, OptionNumber, OptionType, Attribute, Description, FilePath, OptionalData, OptionalDataSize ); ASSERT_EFI_ERROR (Status); CopyGuid (&Option->VendorGuid, VendorGuid); FreePool (Variable); return Status; }
/** Dump capsule status variable. @retval EFI_SUCCESS The capsule status variable is dumped. @retval EFI_UNSUPPORTED Input parameter is not valid. **/ EFI_STATUS DmpCapsuleStatusVariable ( VOID ) { EFI_STATUS Status; UINT32 Index; CHAR16 CapsuleVarName[20]; CHAR16 *TempVarName; EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult; EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp; UINTN CapsuleFileNameSize; CHAR16 CapsuleIndexData[12]; CHAR16 *CapsuleIndex; Status = GetVariable2( L"CapsuleMax", &gEfiCapsuleReportGuid, (VOID **)&CapsuleIndex, NULL ); if (!EFI_ERROR(Status)) { CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16)); CapsuleIndexData[11] = 0; Print(L"CapsuleMax - %s\n", CapsuleIndexData); FreePool(CapsuleIndex); } Status = GetVariable2( L"CapsuleLast", &gEfiCapsuleReportGuid, (VOID **)&CapsuleIndex, NULL ); if (!EFI_ERROR(Status)) { CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16)); CapsuleIndexData[11] = 0; Print(L"CapsuleLast - %s\n", CapsuleIndexData); FreePool(CapsuleIndex); } StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule"); TempVarName = CapsuleVarName + StrLen (CapsuleVarName); Index = 0; while (TRUE) { UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index); Status = GetVariable2 ( CapsuleVarName, &gEfiCapsuleReportGuid, (VOID **) &CapsuleResult, NULL ); if (Status == EFI_NOT_FOUND) { break; } else if (EFI_ERROR(Status)) { continue; } ASSERT (CapsuleResult != NULL); // // display capsule process status // if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) { Print (L"CapsuleName: %s\n", CapsuleVarName); Print (L" Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid); Print (L" Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed); Print (L" Capsule Status: %r\n", CapsuleResult->CapsuleStatus); } if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) { if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) { CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1); Print(L" Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version); Print(L" Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex); Print(L" Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex); Print(L" Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId); if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) { Print(L" Capsule FMP CapsuleFileName: %s\n", (CapsuleResultFmp + 1)); CapsuleFileNameSize = StrSize((CHAR16 *)(CapsuleResultFmp + 1)); if (CapsuleResult->VariableTotalSize > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapsuleFileNameSize) { Print(L" Capsule FMP CapsuleTarget: %s\n", (UINT8 *)(CapsuleResultFmp + 1) + CapsuleFileNameSize); } } } } FreePool(CapsuleResult); Index++; if (Index > 0xFFFF) { break; } } return EFI_SUCCESS; }
/** Dump Provisioned Capsule. @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation. **/ VOID DumpProvisionedCapsule ( IN BOOLEAN DumpCapsuleInfo ) { EFI_STATUS Status; CHAR16 CapsuleVarName[30]; CHAR16 *TempVarName; UINTN Index; EFI_PHYSICAL_ADDRESS *CapsuleDataPtr64; UINT16 *BootNext; CHAR16 BootOptionName[20]; EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; EFI_SHELL_PROTOCOL *ShellProtocol; Index = 0; CapsuleDataPtr64 = NULL; BootNext = NULL; ShellProtocol = GetShellProtocol (); if (ShellProtocol == NULL) { Print (L"Get Shell Protocol Fail\n"); return ; } // // Dump capsule provisioned on Memory // Print (L"#########################\n"); Print (L"### Capsule on Memory ###\n"); Print (L"#########################\n"); StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME); TempVarName = CapsuleVarName + StrLen (CapsuleVarName); while (TRUE) { if (Index > 0) { UnicodeValueToStringS ( TempVarName, sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName), 0, Index, 0 ); } Status = GetVariable2 ( CapsuleVarName, &gEfiCapsuleVendorGuid, (VOID **) &CapsuleDataPtr64, NULL ); if (EFI_ERROR (Status) || CapsuleDataPtr64 == NULL) { if (Index == 0) { Print (L"No data.\n"); } break; } Index++; Print (L"Capsule Description at 0x%08x\n", *CapsuleDataPtr64); DumpBlockDescriptors ((EFI_CAPSULE_BLOCK_DESCRIPTOR*) (UINTN) *CapsuleDataPtr64, DumpCapsuleInfo); } // // Dump capsule provisioned on Disk // Print (L"#########################\n"); Print (L"### Capsule on Disk #####\n"); Print (L"#########################\n"); Status = GetVariable2 ( L"BootNext", &gEfiGlobalVariableGuid, (VOID **) &BootNext, NULL ); if (EFI_ERROR (Status) || BootNext == NULL) { Print (L"Get BootNext Variable Fail. Status = %r\n", Status); } else { UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNext); Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry); if (!EFI_ERROR (Status)) { // // Display description and device path // GetEfiSysPartitionFromBootOptionFilePath (BootNextOptionEntry.FilePath, &DevicePath, &Fs); if(!EFI_ERROR (Status)) { Print (L"Capsules are provisioned on BootOption: %s\n", BootNextOptionEntry.Description); Print (L" %s %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText(DevicePath, TRUE, TRUE)); DumpCapsuleFromDisk (Fs, DumpCapsuleInfo); } } } }
/** Add new boot option for HTTP boot. @param[in] Private Pointer to the driver private data. @param[in] UsingIpv6 Set to TRUE if creating boot option for IPv6. @param[in] Description The description text of the boot option. @param[in] Uri The URI string of the boot file. @retval EFI_SUCCESS The boot option is created successfully. @retval Others Failed to create new boot option. **/ EFI_STATUS HttpBootAddBootOption ( IN HTTP_BOOT_PRIVATE_DATA *Private, IN BOOLEAN UsingIpv6, IN CHAR16 *Description, IN CHAR16 *Uri ) { EFI_DEV_PATH *Node; EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; UINTN Length; CHAR8 AsciiUri[URI_STR_MAX_SIZE]; CHAR16 *CurrentOrder; EFI_STATUS Status; UINTN OrderCount; UINTN TargetLocation; BOOLEAN Found; UINT8 *TempByteBuffer; UINT8 *TempByteStart; UINTN DescSize; UINTN FilePathSize; CHAR16 OptionStr[10]; UINT16 *NewOrder; UINTN Index; NewOrder = NULL; TempByteStart = NULL; NewDevicePath = NULL; NewOrder = NULL; Node = NULL; TmpDevicePath = NULL; CurrentOrder = NULL; if (StrLen (Description) == 0) { return EFI_INVALID_PARAMETER; } // // Convert the scheme to all lower case. // for (Index = 0; Index < StrLen (Uri); Index++) { if (Uri[Index] == L':') { break; } if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') { Uri[Index] -= (CHAR16)(L'A' - L'a'); } } // // Only accept http and https URI. // if ((StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 7) != 0)) { return EFI_INVALID_PARAMETER; } // // Create a new device path by appending the IP node and URI node to // the driver's parent device path // if (!UsingIpv6) { Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH)); if (Node == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH; Node->Ipv4.Header.SubType = MSG_IPv4_DP; SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); } else { Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH)); if (Node == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH; Node->Ipv6.Header.SubType = MSG_IPv6_DP; SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH)); } TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); FreePool (Node); if (TmpDevicePath == NULL) { return EFI_OUT_OF_RESOURCES; } // // Update the URI node with the input boot file URI. // UnicodeStrToAsciiStr (Uri, AsciiUri); Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri); Node = AllocatePool (Length); if (Node == NULL) { Status = EFI_OUT_OF_RESOURCES; FreePool (TmpDevicePath); goto ON_EXIT; } Node->DevPath.Type = MESSAGING_DEVICE_PATH; Node->DevPath.SubType = MSG_URI_DP; SetDevicePathNodeLength (Node, Length); CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri, AsciiStrSize (AsciiUri)); NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); FreePool (Node); FreePool (TmpDevicePath); if (NewDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } // // Get current "BootOrder" variable and find a free target. // Length = 0; Status = GetVariable2 ( L"BootOrder", &gEfiGlobalVariableGuid, (VOID **)&CurrentOrder, &Length ); if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { goto ON_EXIT; } OrderCount = Length / sizeof (UINT16); Found = FALSE; for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) { Found = TRUE; for (Index = 0; Index < OrderCount; Index++) { if (CurrentOrder[Index] == TargetLocation) { Found = FALSE; break; } } if (Found) { break; } } if (TargetLocation == 0xFFFF) { DEBUG ((EFI_D_ERROR, "Could not find unused target index.\n")); Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } else { DEBUG ((EFI_D_INFO, "TargetIndex = %04x.\n", TargetLocation)); } // // Construct and set the "Boot####" variable // DescSize = StrSize(Description); FilePathSize = GetDevicePathSize (NewDevicePath); TempByteBuffer = AllocateZeroPool(sizeof(EFI_LOAD_OPTION) + DescSize + FilePathSize); if (TempByteBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } TempByteStart = TempByteBuffer; *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes TempByteBuffer += sizeof (UINT32); *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength TempByteBuffer += sizeof (UINT16); CopyMem (TempByteBuffer, Description, DescSize); TempByteBuffer += DescSize; CopyMem (TempByteBuffer, NewDevicePath, FilePathSize); UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", L"Boot", TargetLocation); Status = gRT->SetVariable ( OptionStr, &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize, TempByteStart ); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Insert into the order list and set "BootOrder" variable // NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (UINT16)); if (NewOrder == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } CopyMem(NewOrder, CurrentOrder, OrderCount * sizeof(UINT16)); NewOrder[OrderCount] = (UINT16) TargetLocation; Status = gRT->SetVariable ( L"BootOrder", &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, ((OrderCount + 1) * sizeof (UINT16)), NewOrder ); ON_EXIT: if (CurrentOrder != NULL) { FreePool (CurrentOrder); } if (NewOrder != NULL) { FreePool (NewOrder); } if (TempByteStart != NULL) { FreePool (TempByteStart); } if (NewDevicePath != NULL) { FreePool (NewDevicePath); } return Status; }
/** Insert a new ESRT entry into ESRT Cache repository. @param[in] Entry Esrt entry to be set @param[in] Attribute Esrt from Esrt private protocol or FMP instance @retval EFI_SUCCESS Successfully set a variable. **/ EFI_STATUS InsertEsrtEntry( IN EFI_SYSTEM_RESOURCE_ENTRY *Entry, UINTN Attribute ) { EFI_STATUS Status; CHAR16 *VariableName; EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository; UINTN RepositorySize; EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepositoryNew; EsrtRepository = NULL; EsrtRepositoryNew = NULL; // // Get Esrt index buffer // if (Attribute == ESRT_FROM_FMP) { VariableName = EFI_ESRT_FMP_VARIABLE_NAME; } else { VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME; } Status = GetVariable2 ( VariableName, &gEfiCallerIdGuid, (VOID **) &EsrtRepository, &RepositorySize ); if (Status == EFI_NOT_FOUND) { // // If not exist, create new Esrt cache repository // Status = gRT->SetVariable( VariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(EFI_SYSTEM_RESOURCE_ENTRY), Entry ); return Status; } else if (Status == EFI_SUCCESS) { // // if exist, update Esrt cache repository // if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) { DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n")); // // Repository is corrupt. Clear Repository before insert new entry // Status = gRT->SetVariable( VariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, EsrtRepository ); FreePool(EsrtRepository); RepositorySize = 0; EsrtRepository = NULL; } // // Check Repository size constraint // if ((Attribute == ESRT_FROM_FMP && RepositorySize >= PcdGet32(PcdMaxFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) ||(Attribute == ESRT_FROM_NONFMP && RepositorySize >= PcdGet32(PcdMaxNonFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) ) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } EsrtRepositoryNew = AllocatePool(RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY)); if (EsrtRepositoryNew == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } if (RepositorySize != 0 && EsrtRepository != NULL) { CopyMem(EsrtRepositoryNew, EsrtRepository, RepositorySize); } CopyMem((UINT8 *)EsrtRepositoryNew + RepositorySize, Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY)); Status = gRT->SetVariable( VariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY), EsrtRepositoryNew ); } EXIT: if (EsrtRepository != NULL) { FreePool(EsrtRepository); } if (EsrtRepositoryNew != NULL) { FreePool(EsrtRepositoryNew); } return Status; }
/** Update one ESRT entry in ESRT repository @param[in] Entry Esrt entry to be set @param[in] Attribute Esrt from Non Esrt or FMP instance @retval EFI_SUCCESS Successfully Update a variable. @retval EFI_NOT_FOUND The Esrt enry doesn't exist **/ EFI_STATUS UpdateEsrtEntry( IN EFI_SYSTEM_RESOURCE_ENTRY *Entry, UINTN Attribute ) { EFI_STATUS Status; CHAR16 *VariableName; EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository; UINTN RepositorySize; UINTN Index; UINTN EsrtNum; EsrtRepository = NULL; // // Get Esrt index buffer // if (Attribute == ESRT_FROM_FMP) { VariableName = EFI_ESRT_FMP_VARIABLE_NAME; } else { VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME; } Status = GetVariable2 ( VariableName, &gEfiCallerIdGuid, (VOID **) &EsrtRepository, &RepositorySize ); if (!EFI_ERROR(Status)) { // // if exist, update Esrt cache repository // if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) { DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n")); // // Repository is corrupt. Clear Repository before insert new entry // Status = gRT->SetVariable( VariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, EsrtRepository ); Status = EFI_NOT_FOUND; goto EXIT; } Status = EFI_NOT_FOUND; EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY); for (Index = 0; Index < EsrtNum; Index++) { // // Update Esrt entry if it is found in repository // if (CompareGuid(&Entry->FwClass, &EsrtRepository[Index].FwClass)) { CopyMem(&EsrtRepository[Index], Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY)); // // Update New Repository // Status = gRT->SetVariable( VariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, RepositorySize, EsrtRepository ); break; } } } EXIT: if (EsrtRepository != NULL) { FreePool(EsrtRepository); } return Status; }