/*++ Copyright (c) 2000 Microsoft Corporation Module Name: efintldr.c Abstract: Revision History: Jeff Sigman 05/01/00 Created Jeff Sigman 05/10/00 Version 1.5 released Jeff Sigman 10/18/00 Fix for Soft81 bug(s) --*/ #include "precomp.h" // // Open the IA64LDR.EFI image and load the OS // BOOLEAN LaunchOS( IN char* String, IN EFI_HANDLE ImageHandle, IN EFI_FILE_HANDLE* CurDir, IN EFI_LOADED_IMAGE* LoadedImage ) { CHAR16* uniBuf = NULL; BOOLEAN bError = TRUE; EFI_STATUS Status; EFI_HANDLE exeHdl = NULL; EFI_INPUT_KEY Key; EFI_FILE_HANDLE FileHandle = NULL; EFI_DEVICE_PATH* ldrDevPath = NULL; do { // // Convert OS path to unicode from ACSII // uniBuf = RutlUniStrDup(String); if (!uniBuf) { break; } // // Open the ia64ldr.efi // Status = (*CurDir)->Open( *CurDir, &FileHandle, uniBuf, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { break; } ldrDevPath = FileDevicePath(LoadedImage->DeviceHandle, uniBuf); if (!ldrDevPath) { break; } Status = BS->LoadImage( FALSE, ImageHandle, ldrDevPath, NULL, 0, &exeHdl); if (EFI_ERROR(Status)) { break; } Print (L"\nAttempting to launch... %s\n", uniBuf); WaitForSingleEvent(ST->ConIn->WaitForKey, 5000000); ST->ConIn->ReadKeyStroke(ST->ConIn, &Key); // // Clean up // ldrDevPath = RutlFree(ldrDevPath); uniBuf = RutlFree(uniBuf); String = RutlFree(String); // // Disable the cursor // ST->ConOut->EnableCursor(ST->ConOut, FALSE); bError = FALSE; // // Start the OS baby!! // BS->StartImage(exeHdl, 0, NULL); // // If we get here the OS failed to load // bError = TRUE; // // Re-enable the cursor // ST->ConOut->EnableCursor(ST->ConOut, TRUE); } while (FALSE); // // Clean up // if (ldrDevPath) { ldrDevPath = RutlFree(ldrDevPath); } if (uniBuf) { uniBuf = RutlFree(uniBuf); } if (FileHandle) { FileHandle->Close(FileHandle); } if (String) { String = RutlFree(String); } // // Where the heck is the lib for this? // // if (exeHdl) // UnloadImage(&exeHdl); return bError; } // // Struct Cleanup // BOOLEAN FreeBootData( IN VOID* hBootData ) { UINTN i; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; if (!pBootData) { return TRUE; } for (i = 0; i < pBootData->dwIndex; i++) { pBootData->pszSPart[i] = RutlFree(pBootData->pszSPart[i]); pBootData->pszOSLdr[i] = RutlFree(pBootData->pszOSLdr[i]); pBootData->pszLPart[i] = RutlFree(pBootData->pszLPart[i]); pBootData->pszFileN[i] = RutlFree(pBootData->pszFileN[i]); pBootData->pszIdent[i] = RutlFree(pBootData->pszIdent[i]); pBootData->pszShort[i] = RutlFree(pBootData->pszShort[i]); } pBootData->pszShort[pBootData->dwIndex] = RutlFree(pBootData->pszShort[pBootData->dwIndex]); pBootData->pszIdent[pBootData->dwIndex] = RutlFree(pBootData->pszIdent[pBootData->dwIndex]); if (pBootData->pszLoadOpt) { pBootData->pszLoadOpt = RutlFree(pBootData->pszLoadOpt); } pBootData->dwLastKnown = 0; pBootData->dwIndex = 0; pBootData->dwCount = 0; return FALSE; } // // Sort the load options based placing the passed option first // BOOLEAN SortLoadOptions( IN VOID* hBootData, IN char* Buffer, IN UINTN* dwSize, IN UINTN* dwOption, IN UINTN* dwMax, IN EFI_FILE_HANDLE* FileHandle ) { char *FndTok[BOOT_MAX], *Start = NULL, *End = NULL, *NewOpt = NULL, *Sortme = NULL, *Token = NULL, *Last = NULL, *Find = NULL; UINTN i = 0, j = 0, dwIndex = 0, dwStLen = 0, dwOrigLen = 0, dwLen = 0; BOOLEAN bError = FALSE; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; do { // // Find the BOOT_LDOPT option // Start = strstr(Buffer, BOOT_LDOPT); if (!Start) { bError = TRUE; break; } // // Find the end of the option // End = (Start += strlena(BOOT_LDOPT)); while (*(End++) != '\r') ; dwOrigLen = (End - Start) - 1; // // Create buffer to use for temp sort storage // NewOpt = AllocateZeroPool(dwOrigLen + 1); if (!NewOpt) { bError = TRUE; break; } // // Copy only that option to a new buffer // CopyMem(NewOpt, Start, dwOrigLen); // // Replace any leading ';' with a nodebug // while ((NewOpt[i] == ';') && (i < *dwMax)) { FndTok[i] = RutlStrDup(BL_DEBUG_NONE); if (!FndTok[i]) { bError = TRUE; break; } dwIndex += strlena(FndTok[i++]); } // // Remove tokens // Token = strtok(NewOpt, BOOT_TOKEN); while ((Token != NULL) && (Token < (NewOpt + dwOrigLen)) && (i < *dwMax) ) { if (Find = FindAdvLoadOptions(Token)) { // // User has booted using adv options, clearing them out // // Add a NULL at the location of the adv opt // *Find = '\0'; FndTok[i] = RutlStrDup(Token); } else { FndTok[i] = RutlStrDup(Token); if (!FndTok[i]) { bError = TRUE; break; } } dwIndex += strlena(FndTok[i++]); Token = strtok(NULL, BOOT_TOKEN); } while (i < *dwMax) { FndTok[i] = RutlStrDup(BL_DEBUG_NONE); if (!FndTok[i]) { bError = TRUE; break; } dwIndex += strlena(FndTok[i++]); } // // Create buffer to store sorted data // Sortme = AllocateZeroPool(dwLen = dwIndex + *dwMax + 1); if (!Sortme) { bError = TRUE; break; } // // Copy selected option as the first option // if (pBootData->pszLoadOpt) { // // if user has selected an adv boot option, it is plum'd here // dwStLen = strlena(pBootData->pszLoadOpt) + dwLen + strlena(SPACES); Sortme = ReallocatePool(Sortme, dwLen, dwStLen); if (!Sortme) { bError = TRUE; break; } // // they will need to match up later // dwLen = dwStLen; dwIndex = strlena(FndTok[*dwOption]); CopyMem(Sortme, FndTok[*dwOption], dwIndex); dwStLen = dwIndex; dwIndex = strlena(SPACES); CopyMem(Sortme + dwStLen, SPACES, dwIndex); dwStLen += dwIndex; dwIndex = strlena(pBootData->pszLoadOpt); CopyMem(Sortme + dwStLen, pBootData->pszLoadOpt, dwIndex); dwStLen += dwIndex; } else { CopyMem(Sortme, FndTok[*dwOption], strlena(FndTok[*dwOption])); dwStLen = strlena(FndTok[*dwOption]); } // // Append a seperator // *(Sortme + (dwStLen++)) = ';'; // // Smash the rest of the options back in // for (j = 0; j < i; j++) { // // Skip the option that was moved to the front // if (j == *dwOption) { continue; } CopyMem(Sortme + dwStLen, FndTok[j], strlena(FndTok[j])); dwStLen += strlena(FndTok[j]); // // Append a seperator // *(Sortme + (dwStLen++)) = ';'; } dwStLen--; *(Sortme + dwStLen++) = '\r'; *(Sortme + dwStLen++) = '\n'; if (dwLen != dwStLen) { bError = TRUE; break; } // // Write new sorted load options to file // (*FileHandle)->SetPosition(*FileHandle, (Start - Buffer)); (*FileHandle)->Write(*FileHandle, &dwStLen, Sortme); // // Write options that following load options back to file // (*FileHandle)->SetPosition(*FileHandle, (Start - Buffer) + dwStLen - 1); dwStLen = *dwSize - (End - Buffer); (*FileHandle)->Write(*FileHandle, &dwStLen, End); // // Set last known good // if (Last = strstr(End, BOOT_LASTK)) { (*FileHandle)->SetPosition( *FileHandle, (Start - Buffer) + dwLen + (Last - End) - 1); if (pBootData->dwLastKnown) { dwIndex = strlena(LAST_TRUE); (*FileHandle)->Write(*FileHandle, &dwIndex, LAST_TRUE); } else { dwIndex = strlena(LAST_FALSE); (*FileHandle)->Write(*FileHandle, &dwIndex, LAST_FALSE); } } // // Subtract the terminators // dwLen -= 2; if (dwOrigLen <= dwLen) { break; } // // append semi-colon's at the end of the file if we have left over room // // don't reuse 'i', need it below to free // for (j = 0; j < (dwOrigLen - dwLen); j++) { dwStLen = 1; (*FileHandle)->Write(*FileHandle, &dwStLen, ";"); } } while (FALSE); if (Sortme) { Sortme = RutlFree(Sortme); } for (j = 0; j < i; j++) { FndTok[j] = RutlFree(FndTok[j]); } if (NewOpt) { NewOpt = RutlFree(NewOpt); } return bError; } // // Sort the boot options based placing the passed option first // BOOLEAN SortBootData( IN char* Option, IN char* StrArr[], IN UINTN* dwOption, IN UINTN* dwMax, IN char* Buffer ) { char *Start = NULL, *End = NULL, *NewOpt = NULL; UINTN i, dwIndex = 0, dwLen = 0; BOOLEAN bError = TRUE; do { // // Find the option header // Start = strstr(Buffer, Option); if (!Start) { break; } // // Find the end of the option // End = (Start += strlena(Option)); while (*(End++) != '\n') ; dwLen = End - Start; // // Create buffer to use for temp sort storage // NewOpt = AllocateZeroPool(dwLen); if (!NewOpt) { break; } // // Copy only that option to a new buffer // CopyMem(NewOpt, StrArr[*dwOption], strlena(StrArr[*dwOption])); dwIndex += strlena(StrArr[*dwOption]); // // Append a seperator // *(NewOpt+(dwIndex++)) = ';'; for (i = 0; i < *dwMax; i++) { if (i == *dwOption) { continue; } CopyMem(NewOpt + dwIndex, StrArr[i], strlena(StrArr[i])); dwIndex += strlena(StrArr[i]); *(NewOpt+(dwIndex++)) = ';'; } while (dwIndex++ < (dwLen - 1)) { *(NewOpt + (dwIndex - 1)) = ';'; } *(NewOpt + (dwLen - 2)) = '\r'; *(NewOpt + dwLen - 1) = '\n'; if (dwIndex != dwLen) { break; } // // Copy new sorted data in the buffer // CopyMem(Start, NewOpt, dwIndex); bError = FALSE; } while (FALSE); if (NewOpt) { NewOpt = RutlFree(NewOpt); } return bError; } // // Parse options from file data // BOOLEAN OrderBootFile( IN UINTN dwOption, IN char* Buffer, IN VOID* hBootData ) { BOOLEAN bError = TRUE; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; do { // // Find/sort the BOOT_SPART option // if (SortBootData( BOOT_SPART, pBootData->pszSPart, &dwOption, &(pBootData->dwIndex), Buffer)) { Print(L"OrderBootFile() failed for BOOT_SPART option!\n"); break; } // // Find/sort the BOOT_OSLDR option // if (SortBootData( BOOT_OSLDR, pBootData->pszOSLdr, &dwOption, &(pBootData->dwIndex), Buffer)) { Print(L"OrderBootFile() failed for BOOT_OSLDR option!\n"); break; } // // Find/sort the BOOT_LPART option // if (SortBootData( BOOT_LPART, pBootData->pszLPart, &dwOption, &(pBootData->dwIndex), Buffer)) { Print(L"OrderBootFile() failed for BOOT_LPART option!\n"); break; } // // Find/sort the BOOT_FILEN option // if (SortBootData( BOOT_FILEN, pBootData->pszFileN, &dwOption, &(pBootData->dwIndex), Buffer)) { Print(L"OrderBootFile() failed for BOOT_FILEN option!\n"); break; } // // Find/sort the BOOT_IDENT option // if (SortBootData( BOOT_IDENT, pBootData->pszIdent, &dwOption, &(pBootData->dwIndex), Buffer)) { Print(L"OrderBootFile() failed for BOOT_IDENT option!\n"); break; } bError = FALSE; } while (FALSE); return bError; } // // Chop-up name to be short to 'pretty up' the menu // BOOLEAN CreateShortNames( IN VOID* hBootData ) { char *start = NULL, *end = NULL; UINTN i, Len = 0; BOOLEAN bError = FALSE; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; do { for (i = 0; i < pBootData->dwIndex; i++) { start = strstr(pBootData->pszOSLdr[i], wacks); end = strstr(pBootData->pszOSLdr[i], EFIEXT); // // check for foo case (thx jhavens) // if ((end == NULL) || (start == NULL) ) { start = pBootData->pszOSLdr[i]; end = start; while (*(end++) != '\0') ; Len = end - start; } // // Non-foo case, person has atleast one '\' && '.efi' // if (!Len) { start += 1; while (*end != wackc) { if (end <= start) { start = pBootData->pszOSLdr[i]; end = strstr(pBootData->pszOSLdr[i], wacks); break; } end--; } Len = end - start; } if ((end == NULL) || (start == NULL) || (Len < 1) ) { bError = TRUE; break; } pBootData->pszShort[i] = AllocateZeroPool(Len + 1); if (!pBootData->pszShort[i]) { bError = TRUE; break; } CopyMem(pBootData->pszShort[i], start, end - start); Len = 0; start = NULL; end = NULL; } } while (FALSE); return bError; } // // Find the passed option from the file data // BOOLEAN FindOpt( IN char* pszOption, IN char* Buffer, OUT char* pszArray[], OUT UINTN* dwCount ) { char *Start = NULL, *End = NULL, *Option = NULL, *Token = NULL; UINTN dwIndex = 0; BOOLEAN bError = TRUE; do { // // Find the option // Start = strstr(Buffer, pszOption); if (!Start) { break; } // // Find the end of the option // Start += strlena(pszOption); End = Start; while (*(End++) != '\r') ; Option = AllocateZeroPool((End-Start)); if (!Option) { break; } // // Copy only that option to a new buffer // CopyMem(Option, Start, (End-Start)-1); *(Option+((End-Start)-1)) = 0x00; // // Remove tokens // Token = strtok(Option, BOOT_TOKEN); if (!Token) { break; } if (!(*dwCount)) { while ((Token != NULL) && (dwIndex < BOOT_MAX) ) { pszArray[(dwIndex)++] = RutlStrDup(Token); Token = strtok(NULL, BOOT_TOKEN); } *dwCount = dwIndex; } else { while ((Token != NULL) && (dwIndex < *dwCount) ) { pszArray[(dwIndex)++] = RutlStrDup(Token); Token = strtok(NULL, BOOT_TOKEN); } } if (dwIndex == 0) { break; } bError = FALSE; } while (FALSE); if (Option) { Option = RutlFree(Option); } return bError; } // // Get the options in their entirety from the file data // BOOLEAN GetBootData( IN VOID* hBootData, IN char* Buffer ) { UINTN i; char* TempStr = NULL; CHAR16* UniStr = NULL; BOOLEAN bError = TRUE; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; do { // // Find the BOOT_IDENT option // if (FindOpt( BOOT_IDENT, Buffer, pBootData->pszIdent, &pBootData->dwIndex)) { break; } pBootData->pszIdent[pBootData->dwIndex] = RutlStrDup(BL_EXIT_EFI1); if (!pBootData->pszIdent[pBootData->dwIndex]) { break; } // // Find the BOOT_SPART option // if (FindOpt( BOOT_SPART, Buffer, pBootData->pszSPart, &pBootData->dwIndex)) { break; } // // Find the BOOT_OSLDR option // if (FindOpt( BOOT_OSLDR, Buffer, pBootData->pszOSLdr, &pBootData->dwIndex)) { break; } if (CreateShortNames(pBootData)) { break; } // // Append 'exit' to the end of the menu // pBootData->pszShort[pBootData->dwIndex] = RutlStrDup(BL_EXIT_EFI2); if (!pBootData->pszShort[pBootData->dwIndex]) { break; } // // Find the BOOT_LPART option // if (FindOpt( BOOT_LPART, Buffer, pBootData->pszLPart, &pBootData->dwIndex)) { break; } // // Find the BOOT_FILEN option // if (FindOpt( BOOT_FILEN, Buffer, pBootData->pszFileN, &pBootData->dwIndex)) { break; } // // Find the BOOT_CNTDW option // if (TempStr = strstr(Buffer, BOOT_CNTDW)) { UniStr = RutlUniStrDup(TempStr + strlena(BOOT_CNTDW)); if ((UniStr != NULL) && (Atoi(UniStr) > 0) && (Atoi(UniStr) < BOOT_COUNT) ) { pBootData->dwCount = Atoi(UniStr); bError = FALSE; break; } } // // Set the count to the default if setting it failed // if (!pBootData->dwCount) { pBootData->dwCount = BOOT_COUNT; } bError = FALSE; } while (FALSE); if (UniStr) { UniStr = RutlFree(UniStr); } return bError; } // // fill out startup.nsh with the name of this program // void PopulateStartFile( IN EFI_FILE_HANDLE* StartFile ) { UINTN size; CHAR16 UnicodeMarker = UNICODE_BYTE_ORDER_MARK; size = sizeof(UnicodeMarker); (*StartFile)->Write(*StartFile, &size, &UnicodeMarker); size = (StrLen(THISFILE)) * sizeof(CHAR16); (*StartFile)->Write(*StartFile, &size, THISFILE); return; } // // Parse cmdline params // void ParseArgs( IN EFI_FILE_HANDLE* CurDir, IN EFI_LOADED_IMAGE* LoadedImage ) { EFI_STATUS Status; EFI_FILE_HANDLE StartFile = NULL; do { if (MetaiMatch(LoadedImage->LoadOptions, REGISTER1) || MetaiMatch(LoadedImage->LoadOptions, REGISTER2) ) { Status = (*CurDir)->Open( *CurDir, &StartFile, STARTFILE, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); if (EFI_ERROR(Status)) { break; } Status = StartFile->Delete(StartFile); if (EFI_ERROR(Status)) { break; } StartFile = NULL; Status = (*CurDir)->Open( *CurDir, &StartFile, STARTFILE, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); if (!EFI_ERROR(Status)) { PopulateStartFile(&StartFile); } } } while (FALSE); // // Clean up // if (StartFile) { StartFile->Close(StartFile); } return; } // // Read in BOOT.NVR and return buffer of contents // void* ReadBootFile( IN UINTN* Size, IN EFI_FILE_HANDLE* FileHandle ) { char* Buffer = NULL; EFI_STATUS Status; EFI_FILE_INFO* BootInfo = NULL; do { *Size = (SIZE_OF_EFI_FILE_INFO + 255) * sizeof(CHAR16); BootInfo = AllocateZeroPool(*Size); if (!BootInfo) { break; } Status = (*FileHandle)->GetInfo( *FileHandle, &GenericFileInfo, Size, BootInfo); if (EFI_ERROR(Status)) { break; } // // Find out how much we will need to alloc // *Size = (UINTN) BootInfo->FileSize; Buffer = AllocateZeroPool((*Size) + 1); if (!Buffer) { break; } Status = (*FileHandle)->Read(*FileHandle, Size, Buffer); if (EFI_ERROR(Status)) { Buffer = RutlFree(Buffer); break; } } while (FALSE); // // Clean up // if (BootInfo) { BootInfo = RutlFree(BootInfo); } return Buffer; } // // Remove any extra semi-colons from BOOT.NVR // BOOLEAN CleanBootFile( IN EFI_FILE_HANDLE* FileHandle, IN EFI_FILE_HANDLE* CurDir ) { char *Buffer = NULL, *CpBuffer = NULL; UINTN i, Size = 0, NewSize = 0; BOOLEAN bError = TRUE; EFI_STATUS Status; EFI_FILE_HANDLE NewFile = NULL; do { (*FileHandle)->SetPosition(*FileHandle, 0); Buffer = ReadBootFile(&Size, FileHandle); if (!Buffer) { break; } CpBuffer = AllocateZeroPool(Size); if (!CpBuffer) { break; } for (i = 0; i < Size; i++) { if ((*(Buffer + i) == ';') && ((*(Buffer + i + 1) == ';') || (*(Buffer + i + 1) == '\r') || (i + 1 == Size) ) ) { continue; } *(CpBuffer + NewSize) = *(Buffer + i); NewSize++; } // // Remove the exisiting BOOT.NVR // Status = (*FileHandle)->Delete(*FileHandle); if (EFI_ERROR(Status)) { break; } *FileHandle = NULL; Status = (*CurDir)->Open( *CurDir, &NewFile, BOOT_NVR, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); if (EFI_ERROR(Status)) { break; } Status = NewFile->Write(NewFile, &NewSize, CpBuffer); if (EFI_ERROR(Status)) { break; } bError = FALSE; } while (FALSE); // // Clean up // if (NewFile) { NewFile->Close(NewFile); } if (CpBuffer) { CpBuffer = RutlFree(CpBuffer); } if (Buffer) { Buffer = RutlFree(Buffer); } return bError; } // // Backup the BOOT.NVR so we have a fall back // BOOLEAN BackupBootFile( IN char* Buffer, IN UINTN* Size, IN EFI_FILE_HANDLE* CurDir ) { BOOLEAN bError = FALSE; EFI_STATUS Status; EFI_FILE_HANDLE FileHandle = NULL; do { // // Delete the backup file if already exists // Status = (*CurDir)->Open( *CurDir, &FileHandle, BACKUP_NVR, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); if (!EFI_ERROR(Status)) { Status = FileHandle->Delete(FileHandle); if (EFI_ERROR(Status)) { break; } } FileHandle = NULL; // // Copy current file data to a newly created backup file // Status = (*CurDir)->Open( *CurDir, &FileHandle, BACKUP_NVR, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); if (!EFI_ERROR(Status)) { Status = FileHandle->Write(FileHandle, Size, Buffer); } } while (FALSE); // // Clean up // if (FileHandle) { FileHandle->Close(FileHandle); } if (EFI_ERROR(Status)) { bError = TRUE; } return bError; } // // EFI Entry Point // EFI_STATUS EfiMain( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE* ST ) { char* Buffer = NULL; char* OSPath = NULL; UINTN Size = 0, Launch = 0, Menu = 0; BOOT_DATA* pBootData = NULL; EFI_STATUS Status; EFI_FILE_HANDLE FileHandle = NULL, RootFs = NULL; EFI_DEVICE_PATH* DevicePath = NULL; EFI_LOADED_IMAGE* LoadedImage = NULL; do { InitializeLib(ImageHandle, ST); // // Get the device handle and file path to the EFI OS Loader itself. // Status = BS->HandleProtocol( ImageHandle, &LoadedImageProtocol, &LoadedImage); if (EFI_ERROR(Status)) { Print(L"Can not retrieve LoadedImageProtocol handle\n"); break; } Status = BS->HandleProtocol( LoadedImage->DeviceHandle, &DevicePathProtocol, &DevicePath); if (EFI_ERROR(Status) || DevicePath == NULL) { Print(L"Can not find DevicePath handle\n"); break; } // // Open volume for the device where the EFI OS Loader was loaded from // RootFs = LibOpenRoot(LoadedImage->DeviceHandle); if (!RootFs) { Print(L"Can not open the volume for the file system\n"); break; } // // Look for any cmd line params // ParseArgs(&RootFs, LoadedImage); // // Attempt to open the boot.nvr // Status = RootFs->Open( RootFs, &FileHandle, BOOT_NVR, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); if (EFI_ERROR(Status)) { Print(L"Can not open the file %s\n", BOOT_NVR); break; } Buffer = ReadBootFile(&Size, &FileHandle); if (!Buffer) { Print(L"ReadBootFile() failed!\n"); break; } if (BackupBootFile(Buffer, &Size, &RootFs)) { Print(L"BackupBootFile() failed!\n"); break; } // // Alloc for boot file data struct // pBootData = (BOOT_DATA*) AllocateZeroPool(sizeof(BOOT_DATA)); if (!pBootData) { Print(L"Failed to allocate memory for BOOT_DATA!\n"); break; } if (GetBootData(pBootData, Buffer)) { Print(L"Failed in GetBootData()!\n"); break; } Menu = DisplayMenu(pBootData); if (Menu < pBootData->dwIndex) { if (!OrderBootFile(Menu, Buffer, pBootData)) { FileHandle->SetPosition(FileHandle, 0); FileHandle->Write(FileHandle, &Size, Buffer); if (SortLoadOptions( pBootData, Buffer, &Size, &Menu, &(pBootData->dwIndex), &FileHandle) ) { Print(L"Failed to SortLoadOptions()!\n"); break; } if (CleanBootFile(&FileHandle, &RootFs)) { Print(L"Failed to CleanBootFile()!\n"); break; } } else { Print(L"Failed to OrderBootFile()!\n"); break; } } else { break; } OSPath = RutlStrDup(strstr(pBootData->pszOSLdr[Menu], wacks) + 1); if (!OSPath) { Print(L"Failed to allocate memory for OSPath!\n"); break; } Launch = 1; } while (FALSE); // // Clean up // if (pBootData) { if (pBootData->dwIndex) { FreeBootData(pBootData); } pBootData = RutlFree(pBootData); } if (Buffer) { Buffer = RutlFree(Buffer); } if (FileHandle) { FileHandle->Close(FileHandle); } if (Launch) { if (LaunchOS(OSPath, ImageHandle, &RootFs, LoadedImage)) { Print (L"Failed to LaunchOS()!\n"); } } return EFI_SUCCESS; }