#include // // Global Coordinates // #define COL_TITLE 0 #define ROW_TITLE 0 #define COL_OSOPTIONS 2 #define ROW_OSOPTIONS 2 #define COL_PROMPT 0 #define ROW_PROMPT 2 #define CLEAR_LINE L" " #define PROMPT L"Select> " #define NUMBER_OF_USER_OPTIONS 3 // options, plus a space seperator #define MAX_OPTIONS_PER_VAR 7 #define BACKUPNVRFILE L"\\bootentries.bak" VOID InitializeStdOut( IN struct _EFI_SYSTEM_TABLE *SystemTable ) { // // Stash some of the efi stdout pointers // ConOut = SystemTable->ConOut; ClearScreen = ConOut->ClearScreen; SetCursorPosition = ConOut->SetCursorPosition; SetMode = ConOut->SetMode; CursorRow = ConOut->Mode->CursorRow; CursorColumn = ConOut->Mode->CursorColumn; EnableCursor = ConOut->EnableCursor; ConIn = SystemTable->ConIn; // // Set the mode to 80, 25 and clear the screen // SetMode( ConOut, 0 ); } VOID PrintTitle( ) { CHAR16 Buffer[256]; ClearScreen( ConOut ); #if 0 PrintAt( 0, 30, L"%H%s%N\n", TITLE1 ); PrintAt( 0, 30, L"%H%s%N", VER_PRODUCTBUILD ); #endif SPrint( Buffer, sizeof(Buffer), L"%s [Version %d.%d.%d]", TITLE1, VER_PRODUCTMAJORVERSION, VER_PRODUCTMINORVERSION, VER_PRODUCTBUILD ); PrintAt( 0, 30, L"%H%s%N\n", Buffer); } BOOLEAN isWindowsOsUserSelection( UINTN userSelection ) { BOOLEAN status; status = isWindowsOsBootOption((char*)LoadOptions[userSelection], LoadOptionsSize[userSelection] ); return status; } INTN BackupBootOptions( CHAR16* filePath ) { INTN status; // // backup current boot options // Print(L"\nBacking up boot options...\n"); status = SaveAllBootOptions(filePath); if(status != -1) { Print(L"Backed up Boot Options to file: %H%s%N\n",filePath); Print(L"Use %HImport%N command to retrieve saved boot options\n"); } else { Print(L"Could not backup Boot Options to file: %H%s%N!\n",filePath); } return status; } VOID DisplayMainMenu( ) { UINT32 done = FALSE; UINT32 nUserSelection, nSubUserSelection, nModifyVar; CHAR16 szUserSelection[1024]; CHAR16 szOsLoader[1024]; CHAR16 szInput[512]; VOID* SourceBuffer = NULL; UINT32 PartitionCount; EFI_DEVICE_PATH *FilePath; // // Display boot options from nvram. // PrintTitle(); GetBootManagerVars(); DisplayBootOptions(); // // Process user input. // while( !done ) { GetUserSelection( szUserSelection ); // // Handle char string commands // if( (!StriCmp( szUserSelection, L"q")) || (!StriCmp( szUserSelection, L"quit")) || (!StriCmp( szUserSelection, L"Q")) || (!StriCmp( szUserSelection, L"exit")) ) { // // Quit // done = TRUE; } else if( (!StriCmp( szUserSelection, L"d")) || (!StriCmp( szUserSelection, L"D")) || (!StriCmp( szUserSelection, L"display")) ) { // // Display command // // // Choose selection // Print( L"\n" ); nSubUserSelection = GetSubUserSelection( L"Enter boot option to display: ", (UINT32) GetBootOrderCount() ); if( nSubUserSelection != 0 ) { nSubUserSelection--; if (isWindowsOsUserSelection(nSubUserSelection) == FALSE) { Print (L"\n\nThis tool only displays Windows OS boot options\n"); } else { if(DisplayExtended( nSubUserSelection )) ; else { Print( L"\n" ); Print( L"Wrong Boot Option %d Selected\n", nSubUserSelection+1 ); } } Print( L"\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); } // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } else if( (!StriCmp( szUserSelection, L"e")) || (!StriCmp( szUserSelection, L"E")) || (!StriCmp( szUserSelection, L"erase")) ) { // // Erase command // BOOLEAN selectedAll; // // Choose selection // Print( L"\n" ); nSubUserSelection = GetSubUserSelectionOrAll( L"Enter OS boot option to erase (* = All): ", (UINT32) GetBootOrderCount(), &selectedAll ); // // choose the path based on if the user wants all the os boot options whacked or not // if (selectedAll) { // // get user confirmation // Print( L"\n" ); Input( L"This will erase all OS boot options. Are you Sure? ", szInput, sizeof(szInput) ); if( (!StriCmp( szInput, L"y")) || (!StriCmp( szInput, L"Y"))) { // // backup current boot options first // if (BackupBootOptions(BACKUPNVRFILE) != -1) { if(EraseAllOsBootOptions()) { Print(L"\nAll OS Boot Options Erased.\n"); GetBootManagerVars(); } else { Print(L"\nThere are no OS Boot Options to Erase.\n"); } } Print( L"\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); } } else { CHAR16 buf[256]; if( nSubUserSelection > 0 ) { SPrint (buf, sizeof(buf), L"This will erase OS boot option %d. Are you Sure? ", nSubUserSelection); // get user confirmation // Print( L"\n" ); Input( buf, szInput, sizeof(szInput) ); if( (!StriCmp( szInput, L"y")) || (!StriCmp( szInput, L"Y"))) { nSubUserSelection--; if(EraseOsBootOption(nSubUserSelection)) { Print(L"\nBoot Option %d erased.\n", nSubUserSelection + 1); FreeBootManagerVars(); GetBootManagerVars(); } else { Print(L"\nInvalid OS Boot Options specified.\n"); } Print( L"\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); } } } // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } else if( (!StriCmp( szUserSelection, L"p")) || (!StriCmp( szUserSelection, L"P")) || (!StriCmp( szUserSelection, L"push")) ) { // // Push command // // // Choose selection // Print( L"\n" ); nSubUserSelection = GetSubUserSelection( L"Enter the boot option you want to push to top? ", (UINT32) GetBootOrderCount() ); if( nSubUserSelection > 0 ) { nSubUserSelection--; if(PushToTop( nSubUserSelection )) { FreeBootManagerVars(); GetBootManagerVars(); Print( L"\n" ); Print( L"OS Boot Option %d pushed to top of boot order\n", nSubUserSelection+1 ); } else { Print( L"\n" ); Print( L"Wrong Boot Option %d Selected\n", nSubUserSelection+1 ); } Input( L"Press enter to continue", szInput, sizeof(szInput) ); } // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } else if( (!StriCmp( szUserSelection, L"c")) || (!StriCmp( szUserSelection, L"C")) || (!StriCmp( szUserSelection, L"copy")) ) { // // Copy command // // // Choose selection // Print( L"\n" ); nSubUserSelection = GetSubUserSelection( L"Enter OS boot option to copy: ", (UINT32) GetBootOrderCount() ); if( nSubUserSelection != 0 ) { nSubUserSelection--; if(!CopyVar( nSubUserSelection )) { Print( L"\n" ); Print( L"Wrong Boot Option %d Selected\n",nSubUserSelection+1); } else { SetBootManagerVars(); FreeBootManagerVars(); GetBootManagerVars(); Print( L"\n" ); Print( L"Boot Option %d Copied. ",nSubUserSelection+1); } Print( L"\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); } // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } else if( (!StriCmp( szUserSelection, L"x")) || (!StriCmp( szUserSelection, L"X")) || (!StriCmp( szUserSelection, L"export")) ) { // // Save command // CHAR16 filePath[512]; BOOLEAN selectedAll; // // Choose selection // Print( L"\n" ); nSubUserSelection = GetSubUserSelectionOrAll( L"Enter OS boot option to export (* = All): ", (UINT32) GetBootOrderCount(), &selectedAll ); if (nSubUserSelection > 0 || selectedAll) { Print( L"\n" ); Input( L"Enter EXPORT file path: ", filePath, sizeof(filePath) ); if (StrLen(filePath) > 0) { // // choose the path based on if the user wants all the os boot options exported or just one // if (selectedAll) { Print(L"\nSaving %d boot options...\n", GetBootOrderCount()); if(SaveAllBootOptions(filePath) != -1) { Print(L"Saved Boot Options to file: %H%s%N\n",filePath); Print(L"Use %HImport%N command to retrieve saved boot options\n"); } else { Print(L"Could not save Boot Options to file: %H%s%N!\n",filePath); } } else { Print(L"\nSaving boot option %d...\n", nSubUserSelection); if(SaveBootOption(filePath, nSubUserSelection-1) != -1) { Print(L"Saved Boot Option %d to file: %H%s%N\n",nSubUserSelection, filePath); Print(L"Use %HImport%N command to retrieve saved boot option\n"); } else { Print(L"Could not save Boot Option to file: %H%s%N!\n",filePath); } } } } Print( L"\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } else if( (!StriCmp( szUserSelection, L"i")) || (!StriCmp( szUserSelection, L"I")) || (!StriCmp( szUserSelection, L"import")) ) { // // Restore command // CHAR16 filePath[512]; Print( L"\n" ); Input( L"Enter IMPORT file path: ", filePath, sizeof(filePath) ); if (StrLen(filePath) > 0) { if(RestoreFileExists(filePath) == TRUE) { if(RestoreNvr(filePath) != -1) { Print( L"\n" ); Print(L"Imported Boot Options from file: %H%s%N\n",filePath); FreeBootManagerVars(); GetBootManagerVars(); } else { Print(L"Restore failed!\n"); } } else { Print(L"\n\nError: Restore file not found: %s\n\n", filePath); } } Print( L"\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } #if 0 else if( (!StriCmp( szUserSelection, L"a")) || (!StriCmp( szUserSelection, L"A")) || (!StriCmp( szUserSelection, L"add")) ) { // // Add command // // // Get EFI system partition // PartitionCount = GetPartitions(); if( PartitionCount > 0 ) { Print( L"\n" ); Input( L"Name of New BootOption: ", szInput, sizeof(szInput) ); FilePath = FileDevicePath( GetDeviceHandleForPartition(), L"os\\winnt50\\ia64ldr.efi" ); PackAndWriteToNvr( -1, "multi(0)disk(0)rdisk(0)partition(1)", "multi(0)disk(0)rdisk(0)partition(1)\\os\\winnt50\\ia64ldr.efi", "multi(0)disk(0)rdisk(0)partition(2)", "\\WINNT64", szInput[0] ? szInput : L"New Boot Option", "", (char*) FilePath ); Print( L"\nAdded %H%s%N. Use %HModify%N command to change any of the default values.\n", szInput[0] ? szInput : L"New Boot Option" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); FreeBootManagerVars(); GetBootManagerVars(); } else { Print( L"No partitions found. To use this option, you must have an EFI or FAT16\n" ); Print( L"partition that will be used as your System Partition.\n" ); Input( L"Press enter to continue", szInput, sizeof(szInput) ); } // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } #endif else if( (!StriCmp( szUserSelection, L"h")) || (!StriCmp( szUserSelection, L"H")) || (!StriCmp( szUserSelection, L"help")) ) { // // Help command // PrintTitle(); // // Display Help text. // Print( L"\n" ); Print( L"%HDisplay%N - Display an OS boot option's environment variables.\n" ); Print( L"%HModify%N - Modify an OS boot option's environment variable.\n" ); Print( L"%HCopy%N - Copy (duplicate) an OS boot option.\n" ); Print( L"%HExport%N - Export all/one OS boot option(s) to disk.\n" ); Print( L"%HImport%N - Import (and append) OS boot option(s) from disk.\n" ); Print( L"%HErase%N - Erase all OS boot options from NVRAM.\n" ); Print( L"%HPush%N - Push a OS boot option to top of boot order.\n" ); Print( L"%HHelp%N - This display.\n" ); Print( L"%HQuit%N - Quit.\n" ); Print( L"\n"); Print( L"Note: When importing/exporting boot options, all specified file paths\n"); Print( L" are absolute and relative to the current disk device.\n"); Print( L"\n"); Print( L" Example: To import Boot0000 from the Windows loader directory WINNT50.0\n"); Print( L" on fs1, you would run nvrboot.efi on fs1 and use the path:\n"); Print( L"\n"); Print( L" \\EFI\\Microsoft\\WINNT50.0\\Boot0000\n"); Print( L"\n"); Input( L"Press enter to continue", szInput, sizeof(szInput) ); // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } else if( (!StriCmp( szUserSelection, L"m")) || (!StriCmp( szUserSelection, L"M")) || (!StriCmp( szUserSelection, L"modify")) ) { // // Modify command // // // Choose selection // Print( L"\n" ); nSubUserSelection = GetSubUserSelection( L"Enter OS boot option to modify: ", (UINT32) GetBootOrderCount() ); if( nSubUserSelection > 0 ) { nSubUserSelection--; if (isWindowsOsUserSelection(nSubUserSelection) == FALSE) { Print( L"\n\nThis tool only modifies Windows OS boot options\n" ); } else { if(DisplayExtended( nSubUserSelection )) { // // Choose var // nModifyVar = GetSubUserSelection( L"Enter var to modify: ", MAX_OPTIONS_PER_VAR ); if( nModifyVar > 0) { Print( L"\n" ); // // Map variable to env var // switch( nModifyVar ) { case 1: Input( L"LoadIdentifier = ", szInput, sizeof(szInput) ); nModifyVar = DESCRIPTION; break; case 2: Input( L"OsLoadOptions = ", szInput, sizeof(szInput) ); nModifyVar = OSLOADOPTIONS; break; case 3: Print (L"This field currently not modifiable\n"); #if 0 Input( L"EfiOsLoaderFilePath = ", szInput, sizeof(szInput) ); #endif nModifyVar = EFIFILEPATHLIST; break; case 4: Print (L"This field currently not modifiable\n"); #if 0 Input( L"OsLoaderFilePath = ", szInput, sizeof(szInput) ); #endif nModifyVar = OSFILEPATHLIST; break; default: break; } // // Write all vars to NV-RAM // SetFieldFromLoadOption( nSubUserSelection, nModifyVar, szInput ); DisplayExtended(nSubUserSelection); FreeBootManagerVars(); GetBootManagerVars(); } Print( L"\n" ); } } Input( L"Press enter to continue", szInput, sizeof(szInput) ); } } // // Display boot options from nvram // PrintTitle(); DisplayBootOptions(); } } UINT32 GetConfirmation( IN CHAR16 *szConfirm ) { CHAR16 szIn[80]; UINT32 saveRow; Print( L"\n" ); saveRow = CursorRow; if( szConfirm ) { Input( szConfirm, szIn, sizeof(szIn) ); } else { Input( L"Are you sure? ", szIn, sizeof(szIn) ); } // Clear previous input SetCursorPosition( ConOut, 0, saveRow ); PrintAt( 0, saveRow, CLEAR_LINE ); if( (!StriCmp( szIn, L"y")) || (!StriCmp( szIn, L"yes")) ) return TRUE; return FALSE; } VOID GetUserSelection( OUT CHAR16 *szUserSelection ) { UINT32 numSelections; UINT32 row, col; numSelections = (UINT32) GetOsBootOptionsCount(); numSelections += NUMBER_OF_USER_OPTIONS; // note, we use ROW_PROMPT as an offset row = ROW_OSOPTIONS + numSelections + ROW_PROMPT; col = COL_PROMPT; // Clear previous input SetCursorPosition( ConOut, col, row ); PrintAt( col, row, CLEAR_LINE ); // Get the input SetCursorPosition( ConOut, col, row ); Input( PROMPT, szUserSelection, 1024 ); } VOID DisplayBootOptions( ) { UINT32 i; UINT32 j; CHAR16 LoadIdentifier[200]; UINTN bootOrderCount; bootOrderCount = GetBootOrderCount(); if (bootOrderCount > 0) { for ( i=0,j=0; i 0); #endif // // if we are not in debug mode, just let the use know what is // going on other wise the menu may be screwed up // PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + j, L"%2d. (0 length Boot Entry)\n", i+1); } else if(GetLoadIdentifier( i, LoadIdentifier)) { if (isWindowsOsBootOption((char*)LoadOptions[i], LoadOptionsSize[i]) == TRUE) { PrintAt( COL_OSOPTIONS - 1, ROW_OSOPTIONS + j, L"*%2d. %s\n", i+1, LoadIdentifier ); } else { PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + j, L"%2d. %s\n", i+1, LoadIdentifier ); } j++; } } PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"* = Windows OS boot option\n" ); j++; } else { PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS, L"[No Boot Entries Present]\n"); j = 2; } // // Display Maitainence Menu // #if 0 PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(D)%Nisplay %H(M)%Nodify %H(C)%Nopy\n" ); PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(S)%Nave %H(R)%Nestore %H(E)%Nrase\n" ); // PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(A)%Ndd %H(P)%Nush %H(H)%Nelp %H(Q)%Nuit\n" ); PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(P)%Nush %H(H)%Nelp %H(Q)%Nuit\n" ); #endif PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(D)%Nisplay %H(M)%Nodify %H(C)%Nopy E%H(x)%Nport %H(I)%Nmport %H(E)%Nrase %H(P)%Nush %H(H)%Nelp %H(Q)%Nuit\n" ); } #if 0 #define L_SYSTEMPARTITION L"SystemPartition" #define L_OSLOADER L"OsLoader" #define L_OSLOADPARTITION L"OsLoadPartition" #define L_OSLOADFILENAME L"OsLoadFilename" #define L_LOADIDENTIFIER L"LoadIdentifier" #define L_OSLOADOPTIONS L"OsLoadOptions" #define L_OSLOADPATH L"OsLoadOptions" #define L_EFIFILEPATH L"EfiOsLoaderFilePath" #define L_COUNTDOWN L"COUNTDOWN" #define L_AUTOLOAD L"AUTOLOAD" #define L_LASTKNOWNGOOD L"LastKnownGood" #define L_BOOTSELECTION L"BootSelection" #endif BOOLEAN DisplayExtended( IN UINT32 Selection ) { char OsLoadOptions[200]; CHAR16 LoadIdentifier[200]; unsigned char EfiFilePath[1024]; unsigned char OsLoadPath[1024]; CHAR16 FilePathShort[200]; BOOLEAN status; PFILE_PATH pFilePath; #if DEBUG_PACK DisplayELOFromLoadOption(Selection); #endif status = GetOsLoadOptionVars( Selection, LoadIdentifier, OsLoadOptions, EfiFilePath, OsLoadPath ); if (status == FALSE) { return status; } Print( L"\n" ); Print( L"1. LoadIdentifier = %s\n", LoadIdentifier ); Print( L"2. OsLoadOptions = %s\n", OsLoadOptions ); GetFilePathShort( (EFI_DEVICE_PATH*) EfiFilePath, FilePathShort ); Print( L"3. EfiOsLoaderFilePath = %s\n", FilePathShort ); pFilePath = (FILE_PATH*)OsLoadPath; GetFilePathShort( (EFI_DEVICE_PATH*)pFilePath->FilePath, FilePathShort ); Print( L"4. OsLoaderFilePath = %s\n", FilePathShort ); return TRUE; } UINT32 GetSubUserSelectionOrAll( IN CHAR16* szConfirm, IN UINT32 MaxSelection, OUT BOOLEAN* selectedAll ) { CHAR16 szIn[80]; UINT32 nUserSelection = 0; if( szConfirm ) { Input( szConfirm, szIn, sizeof(szIn) ); } else { Input( L"Enter Selection (* = ALL)? ", szIn, sizeof(szIn) ); } *selectedAll = FALSE; if (StrCmp(szIn, L"*") == 0) { *selectedAll = TRUE; } else { nUserSelection = (int) Atoi( szIn ); if(( nUserSelection>0 ) && ( nUserSelection <= MaxSelection)) return nUserSelection; } return 0; } UINT32 GetSubUserSelection( IN CHAR16 *szConfirm, IN UINT32 MaxSelection ) { CHAR16 szIn[80]; UINT32 nUserSelection = 0; if( szConfirm ) { Input( szConfirm, szIn, sizeof(szIn) ); } else { Input( L"Enter Selection? ", szIn, sizeof(szIn) ); } nUserSelection = (int) Atoi( szIn ); if(( nUserSelection>0 ) && ( nUserSelection <= MaxSelection)) return nUserSelection; return 0; }