EFI_STATUS BdsStartBootOption ( IN CHAR16* BootOption ) { EFI_STATUS Status; BDS_LOAD_OPTION *BdsLoadOption; Status = BootOptionFromLoadOptionVariable (BootOption, &BdsLoadOption); if (!EFI_ERROR(Status)) { Status = BootOptionStart (BdsLoadOption); FreePool (BdsLoadOption); if (!EFI_ERROR(Status)) { Status = EFI_SUCCESS; } else { Status = EFI_NOT_STARTED; } } else { Status = EFI_NOT_FOUND; } return Status; }
EFI_STATUS BootMenuMain ( VOID ) { LIST_ENTRY BootOptionsList; UINTN OptionCount; UINTN BootOptionCount; EFI_STATUS Status; LIST_ENTRY* Entry; BDS_LOAD_OPTION* BootOption; UINTN BootOptionSelected; UINTN Index; UINTN BootMainEntryCount; BOOLEAN IsUnicode; BootOption = NULL; BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY); while (TRUE) { // Get Boot#### list BootOptionList (&BootOptionsList); OptionCount = 1; // Display the Boot options for (Entry = GetFirstNode (&BootOptionsList); !IsNull (&BootOptionsList,Entry); Entry = GetNextNode (&BootOptionsList,Entry) ) { BootOption = LOAD_OPTION_FROM_LINK(Entry); Print(L"[%d] %s\n", OptionCount, BootOption->Description); DEBUG_CODE_BEGIN(); CHAR16* DevicePathTxt; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; UINTN CmdLineSize; ARM_BDS_LOADER_TYPE LoaderType; Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); if (EFI_ERROR(Status)) { // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe) DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathToTextProtocol\n")); return Status; } DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootOption->FilePathList, TRUE, TRUE); Print(L"\t- %s\n",DevicePathTxt); // If it is a supported BootEntry then print its details if (IS_ARM_BDS_BOOTENTRY (BootOption)) { OptionalData = BootOption->OptionalData; LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) { if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) { CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize)), TRUE, TRUE); Print(L"\t- Initrd: %s\n", DevicePathTxt); } if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize) > 0) { Print(L"\t- Arguments: %a\n", (&OptionalData->Arguments.LinuxArguments + 1)); } } switch (LoaderType) { case BDS_LOADER_EFI_APPLICATION: Print(L"\t- LoaderType: EFI Application\n"); break; case BDS_LOADER_KERNEL_LINUX_ATAG: Print(L"\t- LoaderType: Linux kernel with ATAG support\n"); break; case BDS_LOADER_KERNEL_LINUX_FDT: Print(L"\t- LoaderType: Linux kernel with FDT support\n"); break; default: Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType); } } else if (BootOption->OptionalData != NULL) { if (IsPrintableString (BootOption->OptionalData, &IsUnicode)) { if (IsUnicode) { Print (L"\t- Arguments: %s\n", BootOption->OptionalData); } else { AsciiPrint ("\t- Arguments: %a\n", BootOption->OptionalData); } } } FreePool(DevicePathTxt); DEBUG_CODE_END(); OptionCount++; } BootOptionCount = OptionCount-1; // Display the hardcoded Boot entries for (Index = 0; Index < BootMainEntryCount; Index++) { Print(L"[%d] %s\n",OptionCount,BootMainEntries[Index]); OptionCount++; } // Request the boot entry from the user BootOptionSelected = 0; while (BootOptionSelected == 0) { Print(L"Start: "); Status = GetHIInputInteger (&BootOptionSelected); if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) { Print(L"Invalid input (max %d)\n",(OptionCount-1)); BootOptionSelected = 0; } } // Start the selected entry if (BootOptionSelected > BootOptionCount) { // Start the hardcoded entry Status = BootMainEntries[BootOptionSelected - BootOptionCount - 1].Callback (&BootOptionsList); } else { // Find the selected entry from the Boot#### list Index = 1; for (Entry = GetFirstNode (&BootOptionsList); !IsNull (&BootOptionsList,Entry); Entry = GetNextNode (&BootOptionsList,Entry) ) { if (Index == BootOptionSelected) { BootOption = LOAD_OPTION_FROM_LINK(Entry); break; } Index++; } Status = BootOptionStart (BootOption); } } // Should never go here }