/** Extract filename from device path. The returned buffer is allocated using AllocateCopyPool. The caller is responsible for freeing the allocated buffer using FreePool(). @param DevicePath Device path. @return A new allocated string that represents the file name. **/ CHAR16 * ExtractFileNameFromDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { CHAR16 *String; CHAR16 *MatchString; CHAR16 *LastMatch; CHAR16 *FileName; UINTN Length; ASSERT(DevicePath != NULL); String = UiDevicePathToStr(DevicePath); MatchString = String; LastMatch = String; while(MatchString != NULL){ LastMatch = MatchString + 1; MatchString = StrStr(LastMatch,L"\\"); } Length = StrLen(LastMatch); FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch); *(FileName + Length) = 0; FreePool(String); return FileName; }
/** This function create a currently loaded Boot Option from the BMM. It then appends this Boot Option to the end of the "BootOrder" list. It also append this Boot Opotion to the end of BootOptionMenu. @param CallbackData The BMM context data. @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. @retval EFI_SUCCESS If function completes successfully. **/ EFI_STATUS Var_UpdateBootOption ( IN BMM_CALLBACK_DATA *CallbackData ) { UINT16 *BootOrderList; UINT16 *NewBootOrderList; UINTN BootOrderListSize; UINT16 BootString[10]; VOID *Buffer; UINTN BufferSize; UINT8 *Ptr; UINT16 Index; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; BOOLEAN OptionalDataExist; EFI_STATUS Status; BMM_FAKE_NV_DATA *NvRamMap; OptionalDataExist = FALSE; NvRamMap = &CallbackData->BmmFakeNvData; Index = BOpt_GetBootOptionNumber () ; UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); if (NvRamMap->BootDescriptionData[0] == 0x0000) { StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString); } BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->BootDescriptionData); BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); if (NvRamMap->BootOptionalData[0] != 0x0000) { OptionalDataExist = TRUE; BufferSize += StrSize (NvRamMap->BootOptionalData); } Buffer = AllocateZeroPool (BufferSize); if (NULL == Buffer) { return EFI_OUT_OF_RESOURCES; } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = FALSE; NewLoadContext->LoadOptionSize = BufferSize; Ptr = (UINT8 *) Buffer; NewLoadContext->LoadOption = Ptr; *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; NewLoadContext->Attributes = *((UINT32 *) Ptr); NewLoadContext->IsActive = TRUE; NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); Ptr += sizeof (UINT32); *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); Ptr += sizeof (UINT16); CopyMem ( Ptr, NvRamMap->BootDescriptionData, StrSize (NvRamMap->BootDescriptionData) ); NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData)); ASSERT (NewLoadContext->Description != NULL); NewMenuEntry->DisplayString = NewLoadContext->Description; CopyMem ( NewLoadContext->Description, (VOID *) Ptr, StrSize (NvRamMap->BootDescriptionData) ); Ptr += StrSize (NvRamMap->BootDescriptionData); CopyMem ( Ptr, CallbackData->LoadContext->FilePathList, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, (VOID *) Ptr, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->OptionNumber = Index; NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL); NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL); if (OptionalDataExist) { Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); CopyMem (Ptr, NvRamMap->BootOptionalData, StrSize (NvRamMap->BootOptionalData)); } Status = gRT->SetVariable ( BootString, &gEfiGlobalVariableGuid, VAR_FLAG, BufferSize, Buffer ); ASSERT_EFI_ERROR (Status); GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize); NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16)); ASSERT (NewBootOrderList != NULL); if (BootOrderList != NULL){ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize); } NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index; if (BootOrderList != NULL) { FreePool (BootOrderList); } Status = gRT->SetVariable ( L"BootOrder", &gEfiGlobalVariableGuid, VAR_FLAG, BootOrderListSize + sizeof (UINT16), NewBootOrderList ); ASSERT_EFI_ERROR (Status); FreePool (NewBootOrderList); NewBootOrderList = NULL; InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); BootOptionMenu.MenuNumber++; return EFI_SUCCESS; }
/** This function create a currently loaded Drive Option from the BMM. It then appends this Driver Option to the end of the "DriverOrder" list. It append this Driver Opotion to the end of DriverOptionMenu. @param CallbackData The BMM context data. @param HiiHandle The HII handle associated with the BMM formset. @param DescriptionData The description of this driver option. @param OptionalData The optional load option. @param ForceReconnect If to force reconnect. @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. @retval EFI_SUCCESS If function completes successfully. **/ EFI_STATUS Var_UpdateDriverOption ( IN BMM_CALLBACK_DATA *CallbackData, IN EFI_HII_HANDLE HiiHandle, IN UINT16 *DescriptionData, IN UINT16 *OptionalData, IN UINT8 ForceReconnect ) { UINT16 Index; UINT16 *DriverOrderList; UINT16 *NewDriverOrderList; UINT16 DriverString[12]; UINTN DriverOrderListSize; VOID *Buffer; UINTN BufferSize; UINT8 *Ptr; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; BOOLEAN OptionalDataExist; EFI_STATUS Status; OptionalDataExist = FALSE; Index = BOpt_GetDriverOptionNumber (); UnicodeSPrint ( DriverString, sizeof (DriverString), L"Driver%04x", Index ); if (*DescriptionData == 0x0000) { StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString); } BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData); BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); if (*OptionalData != 0x0000) { OptionalDataExist = TRUE; BufferSize += StrSize (OptionalData); } Buffer = AllocateZeroPool (BufferSize); if (NULL == Buffer) { return EFI_OUT_OF_RESOURCES; } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); if (NULL == NewMenuEntry) { FreePool (Buffer); return EFI_OUT_OF_RESOURCES; } NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = FALSE; NewLoadContext->LoadOptionSize = BufferSize; Ptr = (UINT8 *) Buffer; NewLoadContext->LoadOption = Ptr; *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1); NewLoadContext->Attributes = *((UINT32 *) Ptr); NewLoadContext->IsActive = TRUE; NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); Ptr += sizeof (UINT32); *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); Ptr += sizeof (UINT16); CopyMem ( Ptr, DescriptionData, StrSize (DescriptionData) ); NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData)); ASSERT (NewLoadContext->Description != NULL); NewMenuEntry->DisplayString = NewLoadContext->Description; CopyMem ( NewLoadContext->Description, (VOID *) Ptr, StrSize (DescriptionData) ); Ptr += StrSize (DescriptionData); CopyMem ( Ptr, CallbackData->LoadContext->FilePathList, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, (VOID *) Ptr, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->OptionNumber = Index; NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL); NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL); if (OptionalDataExist) { Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); CopyMem ( Ptr, OptionalData, StrSize (OptionalData) ); } Status = gRT->SetVariable ( DriverString, &gEfiGlobalVariableGuid, VAR_FLAG, BufferSize, Buffer ); ASSERT_EFI_ERROR (Status); GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16)); ASSERT (NewDriverOrderList != NULL); if (DriverOrderList != NULL){ CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize); } NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index; if (DriverOrderList != NULL) { EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); } Status = gRT->SetVariable ( L"DriverOrder", &gEfiGlobalVariableGuid, VAR_FLAG, DriverOrderListSize + sizeof (UINT16), NewDriverOrderList ); ASSERT_EFI_ERROR (Status); if (DriverOrderList != NULL) { FreePool (DriverOrderList); } DriverOrderList = NULL; FreePool (NewDriverOrderList); InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); DriverOptionMenu.MenuNumber++; return EFI_SUCCESS; }
/** Build up Console Menu based on types passed in. The type can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT and BM_CONSOLE_ERR_CONTEXT_SELECT. @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT and BM_CONSOLE_ERR_CONTEXT_SELECT. @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined. @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", "ConInDev" or "ConErrDev" doesn't exists. @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations. @retval EFI_SUCCESS Function completes successfully. **/ EFI_STATUS GetConsoleMenu ( IN UINTN ConsoleMenuType ) { EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; UINTN Size; UINTN AllCount; UINTN Index; UINTN Index2; BM_MENU_ENTRY *NewMenuEntry; BM_CONSOLE_CONTEXT *NewConsoleContext; TYPE_OF_TERMINAL Terminal; UINTN Com; BM_MENU_OPTION *ConsoleMenu; DevicePath = NULL; AllDevicePath = NULL; AllCount = 0; switch (ConsoleMenuType) { case BM_CONSOLE_IN_CONTEXT_SELECT: ConsoleMenu = &ConsoleInpMenu; DevicePath = GetEfiGlobalVariable (L"ConIn"); AllDevicePath = GetEfiGlobalVariable (L"ConInDev"); break; case BM_CONSOLE_OUT_CONTEXT_SELECT: ConsoleMenu = &ConsoleOutMenu; DevicePath = GetEfiGlobalVariable (L"ConOut"); AllDevicePath = GetEfiGlobalVariable (L"ConOutDev"); break; case BM_CONSOLE_ERR_CONTEXT_SELECT: ConsoleMenu = &ConsoleErrMenu; DevicePath = GetEfiGlobalVariable (L"ErrOut"); AllDevicePath = GetEfiGlobalVariable (L"ErrOutDev"); break; default: return EFI_UNSUPPORTED; } if (NULL == AllDevicePath) { return EFI_NOT_FOUND; } InitializeListHead (&ConsoleMenu->Head); AllCount = EfiDevicePathInstanceCount (AllDevicePath); ConsoleMenu->MenuNumber = 0; // // Following is menu building up for Console Devices selected. // MultiDevicePath = AllDevicePath; Index2 = 0; for (Index = 0; Index < AllCount; Index++) { DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; NewMenuEntry->OptionNumber = Index2; NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst); ASSERT (NewConsoleContext->DevicePath != NULL); NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); if (NULL == NewMenuEntry->DisplayString) { NewMenuEntry->DisplayString = UiDevicePathToStr (NewConsoleContext->DevicePath); } NewConsoleContext->IsTerminal = IsTerminalDevicePath ( NewConsoleContext->DevicePath, &Terminal, &Com ); NewConsoleContext->IsActive = MatchDevicePaths ( DevicePath, NewConsoleContext->DevicePath ); if (NewConsoleContext->IsTerminal) { BOpt_DestroyMenuEntry (NewMenuEntry); } else { Index2++; ConsoleMenu->MenuNumber++; InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); } } return EFI_SUCCESS; }
/** Build a list containing all serial devices. @retval EFI_SUCCESS The function complete successfully. @retval EFI_UNSUPPORTED No serial ports present. **/ EFI_STATUS LocateSerialIo ( VOID ) { UINTN Index; UINTN Index2; UINTN NoHandles; EFI_HANDLE *Handles; EFI_STATUS Status; ACPI_HID_DEVICE_PATH *Acpi; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_SERIAL_IO_PROTOCOL *SerialIo; EFI_DEVICE_PATH_PROTOCOL *Node; EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; BM_MENU_ENTRY *NewMenuEntry; BM_TERMINAL_CONTEXT *NewTerminalContext; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; VENDOR_DEVICE_PATH Vendor; // // Get all handles that have SerialIo protocol installed // InitializeListHead (&TerminalMenu.Head); TerminalMenu.MenuNumber = 0; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles ); if (EFI_ERROR (Status)) { // // No serial ports present // return EFI_UNSUPPORTED; } // // Sort Uart handles array with Acpi->UID from low to high // then Terminal menu can be built from low Acpi->UID to high Acpi->UID // SortedUartHandle (Handles, NoHandles); for (Index = 0; Index < NoHandles; Index++) { // // Check to see whether the handle has DevicePath Protocol installed // gBS->HandleProtocol ( Handles[Index], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath ); Acpi = NULL; for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { break; } // // Acpi points to the node before Uart node // Acpi = (ACPI_HID_DEVICE_PATH *) Node; } if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); if (NewMenuEntry == NULL) { FreePool (Handles); return EFI_OUT_OF_RESOURCES; } NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath); // // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! // coz' the misc data for each platform is not correct, actually it's the device path stored in // datahub which is not completed, so a searching for end of device path will enter a // dead-loop. // NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); if (NULL == NewMenuEntry->DisplayString) { NewMenuEntry->DisplayString = UiDevicePathToStr (DevicePath); } NewMenuEntry->HelpString = NULL; gBS->HandleProtocol ( Handles[Index], &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo ); CopyMem ( &NewTerminalContext->BaudRate, &SerialIo->Mode->BaudRate, sizeof (UINT64) ); CopyMem ( &NewTerminalContext->DataBits, &SerialIo->Mode->DataBits, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->Parity, &SerialIo->Mode->Parity, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->StopBits, &SerialIo->Mode->StopBits, sizeof (UINT8) ); InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); TerminalMenu.MenuNumber++; } } if (Handles != NULL) { FreePool (Handles); } // // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var // OutDevicePath = GetEfiGlobalVariable (L"ConOut"); InpDevicePath = GetEfiGlobalVariable (L"ConIn"); ErrDevicePath = GetEfiGlobalVariable (L"ErrOut"); if (OutDevicePath != NULL) { UpdateComAttributeFromVariable (OutDevicePath); } if (InpDevicePath != NULL) { UpdateComAttributeFromVariable (InpDevicePath); } if (ErrDevicePath != NULL) { UpdateComAttributeFromVariable (ErrDevicePath); } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); if (NULL == NewMenuEntry) { return EFI_NOT_FOUND; } NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; NewTerminalContext->TerminalType = 0; NewTerminalContext->IsConIn = FALSE; NewTerminalContext->IsConOut = FALSE; NewTerminalContext->IsStdErr = FALSE; Vendor.Header.Type = MESSAGING_DEVICE_PATH; Vendor.Header.SubType = MSG_VENDOR_DP; for (Index2 = 0; Index2 < 4; Index2++) { CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID)); SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); NewDevicePath = AppendDevicePathNode ( NewTerminalContext->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Vendor ); if (NewMenuEntry->HelpString != NULL) { FreePool (NewMenuEntry->HelpString); } // // NewMenuEntry->HelpString = UiDevicePathToStr (NewDevicePath); // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; // NewMenuEntry->HelpString = NULL; if (MatchDevicePaths (OutDevicePath, NewDevicePath)) { NewTerminalContext->IsConOut = TRUE; NewTerminalContext->TerminalType = (UINT8) Index2; } if (MatchDevicePaths (InpDevicePath, NewDevicePath)) { NewTerminalContext->IsConIn = TRUE; NewTerminalContext->TerminalType = (UINT8) Index2; } if (MatchDevicePaths (ErrDevicePath, NewDevicePath)) { NewTerminalContext->IsStdErr = TRUE; NewTerminalContext->TerminalType = (UINT8) Index2; } } } return EFI_SUCCESS; }
/** Build up all DriverOptionMenu @param CallbackData The BMM context data. @retval EFI_SUCESS The functin completes successfully. @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable. **/ EFI_STATUS BOpt_GetDriverOptions ( IN BMM_CALLBACK_DATA *CallbackData ) { UINTN Index; UINT16 DriverString[12]; UINT8 *LoadOptionFromVar; UINTN DriverOptionSize; UINT16 *DriverOrderList; UINTN DriverOrderListSize; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; UINT8 *LoadOptionPtr; UINTN StringSize; UINTN OptionalDataSize; UINT8 *LoadOptionEnd; DriverOrderListSize = 0; DriverOrderList = NULL; DriverOptionSize = 0; LoadOptionFromVar = NULL; BOpt_FreeMenu (&DriverOptionMenu); InitializeListHead (&DriverOptionMenu.Head); // // Get the DriverOrder from the Var // GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); if (DriverOrderList == NULL) { return EFI_NOT_FOUND; } for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { UnicodeSPrint ( DriverString, sizeof (DriverString), L"Driver%04x", DriverOrderList[Index] ); // // Get all loadoptions from the VAR // GetEfiGlobalVariable2 (DriverString, (VOID **) &LoadOptionFromVar, &DriverOptionSize); if (LoadOptionFromVar == NULL) { continue; } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; LoadOptionPtr = LoadOptionFromVar; LoadOptionEnd = LoadOptionFromVar + DriverOptionSize; NewMenuEntry->OptionNumber = DriverOrderList[Index]; NewLoadContext->Deleted = FALSE; NewLoadContext->IsLegacy = FALSE; // // LoadOption is a pointer type of UINT8 // for easy use with following LOAD_OPTION // embedded in this struct // NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; LoadOptionPtr += sizeof (UINT32); NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; LoadOptionPtr += sizeof (UINT16); StringSize = StrSize ((UINT16 *) LoadOptionPtr); NewLoadContext->Description = AllocateZeroPool (StringSize); ASSERT (NewLoadContext->Description != NULL); CopyMem ( NewLoadContext->Description, (UINT16 *) LoadOptionPtr, StringSize ); NewMenuEntry->DisplayString = NewLoadContext->Description; NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL); LoadOptionPtr += StringSize; NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, NewLoadContext->FilePathListLength ); NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL); LoadOptionPtr += NewLoadContext->FilePathListLength; if (LoadOptionPtr < LoadOptionEnd) { OptionalDataSize = DriverOptionSize - sizeof (UINT32) - sizeof (UINT16) - StringSize - NewLoadContext->FilePathListLength; NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); ASSERT (NewLoadContext->OptionalData != NULL); CopyMem ( NewLoadContext->OptionalData, LoadOptionPtr, OptionalDataSize ); } InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); FreePool (LoadOptionFromVar); } if (DriverOrderList != NULL) { FreePool (DriverOrderList); } DriverOptionMenu.MenuNumber = Index; return EFI_SUCCESS; }
/** Find drivers that will be added as Driver#### variables from handles in current system environment All valid handles in the system except those consume SimpleFs, LoadFile are stored in DriverMenu for future use. @retval EFI_SUCCESS The function complets successfully. @return Other value if failed to build the DriverMenu. **/ EFI_STATUS BOpt_FindDrivers ( VOID ) { UINTN NoDevicePathHandles; EFI_HANDLE *DevicePathHandle; UINTN Index; EFI_STATUS Status; BM_MENU_ENTRY *NewMenuEntry; BM_HANDLE_CONTEXT *NewHandleContext; EFI_HANDLE CurHandle; UINTN OptionNumber; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; EFI_LOAD_FILE_PROTOCOL *LoadFile; SimpleFs = NULL; LoadFile = NULL; InitializeListHead (&DriverMenu.Head); // // At first, get all handles that support Device Path // protocol which is the basic requirement for // Driver#### // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &NoDevicePathHandles, &DevicePathHandle ); if (EFI_ERROR (Status)) { return Status; } OptionNumber = 0; for (Index = 0; Index < NoDevicePathHandles; Index++) { CurHandle = DevicePathHandle[Index]; Status = gBS->HandleProtocol ( CurHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &SimpleFs ); if (Status == EFI_SUCCESS) { continue; } Status = gBS->HandleProtocol ( CurHandle, &gEfiLoadFileProtocolGuid, (VOID **) &LoadFile ); if (Status == EFI_SUCCESS) { continue; } NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); if (NULL == NewMenuEntry) { FreePool (DevicePathHandle); return EFI_OUT_OF_RESOURCES; } NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; NewHandleContext->Handle = CurHandle; NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath); NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle,0,NewMenuEntry->DisplayString,NULL); NewMenuEntry->HelpString = NULL; NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; NewMenuEntry->OptionNumber = OptionNumber; OptionNumber++; InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); } if (DevicePathHandle != NULL) { FreePool (DevicePathHandle); } DriverMenu.MenuNumber = OptionNumber; return EFI_SUCCESS; }
/** Build the BootOptionMenu according to BootOrder Variable. This Routine will access the Boot#### to get EFI_LOAD_OPTION. @param CallbackData The BMM context data. @return EFI_NOT_FOUND Fail to find "BootOrder" variable. @return EFI_SUCESS Success build boot option menu. **/ EFI_STATUS BOpt_GetBootOptions ( IN BMM_CALLBACK_DATA *CallbackData ) { UINTN Index; UINT16 BootString[10]; UINT8 *LoadOptionFromVar; UINTN BootOptionSize; BOOLEAN BootNextFlag; UINT16 *BootOrderList; UINTN BootOrderListSize; UINT16 *BootNext; UINTN BootNextSize; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; UINT8 *LoadOptionPtr; UINTN StringSize; UINTN OptionalDataSize; UINT8 *LoadOptionEnd; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN MenuCount; UINT8 *Ptr; EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; UINTN BootOptionCount; MenuCount = 0; BootOrderListSize = 0; BootNextSize = 0; BootOrderList = NULL; BootNext = NULL; LoadOptionFromVar = NULL; BOpt_FreeMenu (&BootOptionMenu); InitializeListHead (&BootOptionMenu.Head); // // Get the BootOrder from the Var // GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize); if (BootOrderList == NULL) { return EFI_NOT_FOUND; } // // Get the BootNext from the Var // GetEfiGlobalVariable2 (L"BootNext", (VOID **) &BootNext, &BootNextSize); if (BootNext != NULL) { if (BootNextSize != sizeof (UINT16)) { FreePool (BootNext); BootNext = NULL; } } BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { // // Don't display the hidden/inactive boot option // if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { continue; } UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); // // Get all loadoptions from the VAR // GetEfiGlobalVariable2 (BootString, (VOID **) &LoadOptionFromVar, &BootOptionSize); if (LoadOptionFromVar == NULL) { continue; } if (BootNext != NULL) { BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); } else { BootNextFlag = FALSE; } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); ASSERT (NULL != NewMenuEntry); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; LoadOptionPtr = LoadOptionFromVar; LoadOptionEnd = LoadOptionFromVar + BootOptionSize; NewMenuEntry->OptionNumber = BootOrderList[Index]; NewLoadContext->Deleted = FALSE; NewLoadContext->IsBootNext = BootNextFlag; // // Is a Legacy Device? // Ptr = (UINT8 *) LoadOptionFromVar; // // Attribute = *(UINT32 *)Ptr; // Ptr += sizeof (UINT32); // // FilePathSize = *(UINT16 *)Ptr; // Ptr += sizeof (UINT16); // // Description = (CHAR16 *)Ptr; // Ptr += StrSize ((CHAR16 *) Ptr); // // Now Ptr point to Device Path // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { NewLoadContext->IsLegacy = TRUE; } else { NewLoadContext->IsLegacy = FALSE; } // // LoadOption is a pointer type of UINT8 // for easy use with following LOAD_OPTION // embedded in this struct // NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; LoadOptionPtr += sizeof (UINT32); NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; LoadOptionPtr += sizeof (UINT16); StringSize = StrSize((UINT16*)LoadOptionPtr); NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr)); ASSERT (NewLoadContext->Description != NULL); StrCpyS (NewLoadContext->Description, StrSize((UINT16*)LoadOptionPtr) / sizeof (UINT16), (UINT16*)LoadOptionPtr); ASSERT (NewLoadContext->Description != NULL); NewMenuEntry->DisplayString = NewLoadContext->Description; NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL); LoadOptionPtr += StringSize; NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, NewLoadContext->FilePathListLength ); NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL); LoadOptionPtr += NewLoadContext->FilePathListLength; if (LoadOptionPtr < LoadOptionEnd) { OptionalDataSize = BootOptionSize - sizeof (UINT32) - sizeof (UINT16) - StringSize - NewLoadContext->FilePathListLength; NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); ASSERT (NewLoadContext->OptionalData != NULL); CopyMem ( NewLoadContext->OptionalData, LoadOptionPtr, OptionalDataSize ); } InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); MenuCount++; FreePool (LoadOptionFromVar); } EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); if (BootNext != NULL) { FreePool (BootNext); } if (BootOrderList != NULL) { FreePool (BootOrderList); } BootOptionMenu.MenuNumber = MenuCount; return EFI_SUCCESS; }
/** Enumerate possible boot options. **/ VOID EnumerateBootOptions ( 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; UINT16 KeyInput; UINTN DestMax; DeviceType = (UINT16) -1; // // 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 (); 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; KeyInput = 0; NeedEndOp = FALSE; for (Index = 0; Index < BootOptionCount; Index++) { // // At this stage we are creating a menu entry, thus the Keys are reproduceable // KeyInput++; // // 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 = UiDevicePathToStr (BootOption[Index].FilePath); TempSize = StrSize (TempStr); DestMax = (TempSize + StrSize (L"Device Path : ")) / sizeof(CHAR16); HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : ")); ASSERT (HelpString != NULL); StrCatS (HelpString, DestMax, L"Device Path : "); StrCatS (HelpString, DestMax, TempStr); HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); HiiCreateActionOpCode ( StartOpCodeHandle, KeyInput, 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); }
/** This function create a currently loaded Boot Option from the BMM. It then appends this Boot Option to the end of the "BootOrder" list. It also append this Boot Opotion to the end of BootOptionMenu. @param CallbackData The BMM context data. @retval other Contain some errors when excuting this function. See function EfiBootManagerInitializeLoadOption/EfiBootManagerAddLoadOptionVariabl for detail return information. @retval EFI_SUCCESS If function completes successfully. **/ EFI_STATUS Var_UpdateBootOption ( IN BMM_CALLBACK_DATA *CallbackData ) { UINT16 BootString[10]; UINT16 Index; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; BOOLEAN OptionalDataExist; EFI_STATUS Status; BMM_FAKE_NV_DATA *NvRamMap; EFI_BOOT_MANAGER_LOAD_OPTION LoadOption; UINT8 *OptionalData; UINT32 OptionalDataSize; OptionalDataExist = FALSE; NvRamMap = &CallbackData->BmmFakeNvData; OptionalData = NULL; OptionalDataSize = 0; Index = BOpt_GetBootOptionNumber () ; UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); if (NvRamMap->BootDescriptionData[0] == 0x0000) { StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString); } if (NvRamMap->BootOptionalData[0] != 0x0000) { OptionalDataExist = TRUE; OptionalData = (UINT8 *)NvRamMap->BootOptionalData; OptionalDataSize = (UINT32)StrSize (NvRamMap->BootOptionalData); } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } Status = EfiBootManagerInitializeLoadOption ( &LoadOption, Index, LoadOptionTypeBoot, LOAD_OPTION_ACTIVE, NvRamMap->BootDescriptionData, CallbackData->LoadContext->FilePathList, OptionalData, OptionalDataSize ); if (EFI_ERROR (Status)){ return Status; } Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 ); if (EFI_ERROR (Status)) { EfiBootManagerFreeLoadOption(&LoadOption); return Status; } NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = FALSE; NewLoadContext->Attributes = LoadOption.Attributes; NewLoadContext->FilePathListLength = (UINT16) GetDevicePathSize (LoadOption.FilePath); NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData)); ASSERT (NewLoadContext->Description != NULL); NewMenuEntry->DisplayString = NewLoadContext->Description; CopyMem ( NewLoadContext->Description, LoadOption.Description, StrSize (NvRamMap->BootDescriptionData) ); NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, LoadOption.FilePath, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->OptionNumber = Index; NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL); NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL); if (OptionalDataExist) { NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize); ASSERT (NewLoadContext->OptionalData != NULL); CopyMem ( NewLoadContext->OptionalData, LoadOption.OptionalData, LoadOption.OptionalDataSize ); } InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); BootOptionMenu.MenuNumber++; EfiBootManagerFreeLoadOption(&LoadOption); return EFI_SUCCESS; }
/** This function create a currently loaded Drive Option from the BMM. It then appends this Driver Option to the end of the "DriverOrder" list. It append this Driver Opotion to the end of DriverOptionMenu. @param CallbackData The BMM context data. @param HiiHandle The HII handle associated with the BMM formset. @param DescriptionData The description of this driver option. @param OptionalData The optional load option. @param ForceReconnect If to force reconnect. @retval other Contain some errors when excuting this function.See function EfiBootManagerInitializeLoadOption/EfiBootManagerAddLoadOptionVariabl for detail return information. @retval EFI_SUCCESS If function completes successfully. **/ EFI_STATUS Var_UpdateDriverOption ( IN BMM_CALLBACK_DATA *CallbackData, IN EFI_HII_HANDLE HiiHandle, IN UINT16 *DescriptionData, IN UINT16 *OptionalData, IN UINT8 ForceReconnect ) { UINT16 Index; UINT16 DriverString[12]; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; BOOLEAN OptionalDataExist; EFI_STATUS Status; EFI_BOOT_MANAGER_LOAD_OPTION LoadOption; UINT8 *OptionalDesData; UINT32 OptionalDataSize; OptionalDataExist = FALSE; OptionalDesData = NULL; OptionalDataSize = 0; Index = BOpt_GetDriverOptionNumber (); UnicodeSPrint ( DriverString, sizeof (DriverString), L"Driver%04x", Index ); if (*DescriptionData == 0x0000) { StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString); } if (*OptionalData != 0x0000) { OptionalDataExist = TRUE; OptionalDesData = (UINT8 *)OptionalData; OptionalDataSize = (UINT32)StrSize (OptionalData); } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } Status = EfiBootManagerInitializeLoadOption ( &LoadOption, Index, LoadOptionTypeDriver, LOAD_OPTION_ACTIVE | (ForceReconnect << 1), DescriptionData, CallbackData->LoadContext->FilePathList, OptionalDesData, OptionalDataSize ); if (EFI_ERROR (Status)){ return Status; } Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 ); if (EFI_ERROR (Status)) { EfiBootManagerFreeLoadOption(&LoadOption); return Status; } NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = FALSE; NewLoadContext->Attributes = LoadOption.Attributes; NewLoadContext->FilePathListLength = (UINT16)GetDevicePathSize (LoadOption.FilePath); NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData)); ASSERT (NewLoadContext->Description != NULL); NewMenuEntry->DisplayString = NewLoadContext->Description; CopyMem ( NewLoadContext->Description, LoadOption.Description, StrSize (DescriptionData) ); NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, LoadOption.FilePath, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->OptionNumber = Index; NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL); NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL); if (OptionalDataExist) { NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize); ASSERT (NewLoadContext->OptionalData != NULL); CopyMem ( NewLoadContext->OptionalData, LoadOption.OptionalData, LoadOption.OptionalDataSize ); } InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); DriverOptionMenu.MenuNumber++; EfiBootManagerFreeLoadOption(&LoadOption); return EFI_SUCCESS; }