EFI_STATUS StartDefaultBootOnTimeout ( VOID ) { UINTN Size; UINT16 Timeout; UINT16 *TimeoutPtr; EFI_EVENT WaitList[2]; UINTN WaitIndex; UINT16 *BootOrder = NULL; UINTN BootOrderSize = 0; UINTN Index; CHAR16 BootVariableName[9]; EFI_STATUS Status; EFI_INPUT_KEY Key; LIST_ENTRY BootOptionsList; BOOLEAN IsFlashBootFirst = FALSE; BOOLEAN FlashBootSupport = FALSE; // Get the Boot Option Order from the environment variable (a default value should have been created) Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "%a(%d):Return a error Status\n", __FUNCTION__,__LINE__)); } Status = GetBootDeviceTypeInfo(); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "%a(%d):Return a error Status\n", __FUNCTION__,__LINE__)); } Status = OemBootOrderSeting(BootOrder,BootOrderSize,&IsFlashBootFirst,&FlashBootSupport); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "%a(%d):Return a error Status\n", __FUNCTION__,__LINE__)); } // Update (or Create) the BootOrder environment variable Status = gRT->SetVariable ( L"BootOrder", &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, BootOrderSize, BootOrder ); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "%a(%d):SetVariable failed!\n", __FUNCTION__,__LINE__)); } Size = sizeof(UINT16); Timeout = (UINT16)PcdGet16 (PcdPlatformBootTimeOut); Status = GetGlobalEnvironmentVariable (L"Timeout", &Timeout, &Size, (VOID**)&TimeoutPtr); if (!EFI_ERROR (Status)) { Timeout = *TimeoutPtr; FreePool (TimeoutPtr); } if (Timeout != 0xFFFF) { if (Timeout > 0) { // Create the waiting events (keystroke and 1sec timer) gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[0]); gBS->SetTimer (WaitList[0], TimerPeriodic, EFI_SET_TIMER_TO_SECOND); WaitList[1] = gST->ConIn->WaitForKey; // Start the timer WaitIndex = 0; Print(L"The default boot selection will start in "); while ((Timeout > 0) && (WaitIndex == 0)) { Print(L"%3d seconds",Timeout); gBS->WaitForEvent (2, WaitList, &WaitIndex); if (WaitIndex == 0) { Print(L"\b\b\b\b\b\b\b\b\b\b\b"); Timeout--; } } // Discard key in the buffer do { Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); } while(!EFI_ERROR(Status)); gBS->CloseEvent (WaitList[0]); Print(L"\n\r"); } // In case of Timeout we start the default boot selection if (Timeout == 0) { // Get the Boot Option Order from the environment variable (a default value should have been created) Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "%a(%d):Return a error Status\n", __FUNCTION__,__LINE__)); } //display the final BootOrder EnviromentVariable, we'll start OS with it! BootOptionList (&BootOptionsList); DisplayBootOptions(&BootOptionsList); if(FlashBootSupport) { if(IsFlashBootFirst) { Print(L"Bds TimeOut First Start Boot Option [FLASH] ....Begin!...\n\r"); Flash_Start_OS (); Print(L"Bds TimeOut First Start Boot Option [FLASH] ....Fail!...\n\r"); } } for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOrder[Index]); OemPreStartBootOptionAction(BootOrder[Index]); Print(L"Bds TimeOut Start Boot Option [%s] ....Begin!...\n\r",BootVariableName); Status = BdsStartBootOption (BootVariableName); if(!EFI_ERROR(Status)){ // Boot option returned successfully, hence don't need to start next boot option break; } Print(L"Bds TimeOut Start Boot Option [%s] ....Fail!...\n\r",BootVariableName); } if(FlashBootSupport) { if(!IsFlashBootFirst) { Print(L"Bds TimeOut Start Boot Option [FLASH] ....Begin!...\n\r"); Flash_Start_OS (); Print(L"Bds TimeOut Start Boot Option [FLASH] ....Fail!...\n\r"); } }else{} // We only free it if the UEFI Variable 'BootOrder' was already existing if (BootOrderSize > sizeof(UINT16)) { FreePool (BootOrder); } OpenAlarmLed(); Print(L"[WARNING]Bds TimeOut: All Boot Option Start Fail! Lighting The Alarm Led!!! \n\r"); } } return EFI_SUCCESS; }
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 }
EFI_STATUS GetBootDeviceTypeInfo ( VOID ) { EFI_STATUS Status = EFI_SUCCESS; LIST_ENTRY BootOptionsList; LIST_ENTRY* Entry; UINT16 *SataDes = NULL; UINT16 *MacDes = NULL; UINTN SataDesSize = 0; UINTN MacDesSize = 0; BDS_LOAD_OPTION* BootOption; UINTN OptionCount = 0; CHAR16* SataStr = L"Sata"; CHAR16* MacStr = L"MAC"; CHAR16* DevicePathTxt = NULL; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol = NULL; // Get Boot#### list BootOptionList (&BootOptionsList); // 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(); 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); //DEBUG_CODE_END(); //FIND SATA BOOT DEVICES if(!(StringFind(DevicePathTxt, SataStr))) { if(SataDesSize != 0) { SataDes = ReallocatePool (SataDesSize, SataDesSize + sizeof(UINT16), SataDes); SataDes[SataDesSize / sizeof(UINT16)] = BootOption->LoadOptionIndex; SataDesSize += sizeof(UINT16); }else{ SataDesSize = sizeof(UINT16); SataDes = &(BootOption->LoadOptionIndex); } // Print(L"liuhuan SATA boot num: %d\n",SataDesSize / sizeof(UINT16)); } //FIND PXE BOOT DEVICES if(!(StringFind(DevicePathTxt, MacStr) )) { if(MacDesSize != 0) { MacDes = ReallocatePool (MacDesSize, MacDesSize + sizeof(UINT16), MacDes); MacDes[MacDesSize / sizeof(UINT16)] = BootOption->LoadOptionIndex; MacDesSize += sizeof(UINT16); }else{ MacDesSize = sizeof(UINT16); MacDes = &(BootOption->LoadOptionIndex); } // Print(L"liuhuan PXE boot num: %d\n",MacDesSize / sizeof(UINT16)); } //FreePool(DevicePathTxt); OptionCount++; } OemGetSataBootNum(SataDesSize); OemGetPXEBootNum(MacDesSize); if(SataDes != NULL) { FreePool(SataDes); } if(MacDes != NULL) { FreePool(MacDes); } if(DevicePathTxt != NULL) { FreePool(DevicePathTxt); } return EFI_SUCCESS; }