EFIAPI GetManFileName( IN CONST CHAR16 *ManFileName ) { CHAR16 *Buffer; if (ManFileName == NULL) { return (NULL); } // // Fix the file name // if (StrnCmp(ManFileName+StrLen(ManFileName)-4, L".man", 4)==0) { Buffer = AllocateCopyPool(StrSize(ManFileName), ManFileName); } else { Buffer = AllocateZeroPool(StrSize(ManFileName) + 4*sizeof(CHAR16)); if (Buffer != NULL) { StrnCpyS( Buffer, (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16), ManFileName, StrLen(ManFileName) ); StrnCatS( Buffer, (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16), L".man", 4 ); } } return (Buffer); }
EFIAPI GetExecuatableFileName ( IN CONST CHAR16 *NameString ) { CHAR16 *Buffer; CHAR16 *SuffixStr; if (NameString == NULL) { return (NULL); } // // Fix the file name // if (StrnCmp(NameString+StrLen(NameString)-StrLen(L".efi"), L".efi", StrLen(L".efi"))==0) { Buffer = AllocateCopyPool(StrSize(NameString), NameString); } else if (StrnCmp(NameString+StrLen(NameString)-StrLen(L".man"), L".man", StrLen(L".man"))==0) { Buffer = AllocateCopyPool(StrSize(NameString), NameString); if (Buffer != NULL) { SuffixStr = Buffer+StrLen(Buffer)-StrLen(L".man"); StrnCpyS (SuffixStr, StrSize(L".man")/sizeof(CHAR16), L".efi", StrLen(L".efi")); } } else { Buffer = AllocateZeroPool(StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16)); if (Buffer != NULL) { StrnCpyS( Buffer, (StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16))/sizeof(CHAR16), NameString, StrLen(NameString) ); StrnCatS( Buffer, (StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16))/sizeof(CHAR16), L".efi", StrLen(L".efi") ); } } return (Buffer); }
/** Perform the memory test base on the memory test intensive level, and update the memory resource. @param Level The memory test intensive level. @retval EFI_STATUS Success test all the system memory and update the memory resource **/ EFI_STATUS EFIAPI BdsMemoryTest ( IN EXTENDMEM_COVERAGE_LEVEL Level ) { EFI_STATUS Status; EFI_STATUS KeyStatus; EFI_STATUS InitStatus; EFI_STATUS ReturnStatus; BOOLEAN RequireSoftECCInit; EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; UINT64 TestedMemorySize; UINT64 TotalMemorySize; UINTN TestPercent; UINT64 PreviousValue; BOOLEAN ErrorOut; BOOLEAN TestAbort; EFI_INPUT_KEY Key; CHAR16 StrPercent[80]; CHAR16 *StrTotalMemory; CHAR16 *Pos; CHAR16 *TmpStr; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; BOOLEAN IsFirstBoot; UINT32 TempData; UINTN StrTotalMemorySize; ReturnStatus = EFI_SUCCESS; ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); StrTotalMemorySize = 128; Pos = AllocateZeroPool (StrTotalMemorySize); if (Pos == NULL) { return ReturnStatus; } StrTotalMemory = Pos; TestedMemorySize = 0; TotalMemorySize = 0; PreviousValue = 0; ErrorOut = FALSE; TestAbort = FALSE; SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); RequireSoftECCInit = FALSE; Status = gBS->LocateProtocol ( &gEfiGenericMemTestProtocolGuid, NULL, (VOID **) &GenMemoryTest ); if (EFI_ERROR (Status)) { FreePool (Pos); return EFI_SUCCESS; } InitStatus = GenMemoryTest->MemoryTestInit ( GenMemoryTest, Level, &RequireSoftECCInit ); if (InitStatus == EFI_NO_MEDIA) { // // The PEI codes also have the relevant memory test code to check the memory, // it can select to test some range of the memory or all of them. If PEI code // checks all the memory, this BDS memory test will has no not-test memory to // do the test, and then the status of EFI_NO_MEDIA will be returned by // "MemoryTestInit". So it does not need to test memory again, just return. // FreePool (Pos); return EFI_SUCCESS; } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } } else { DEBUG ((EFI_D_INFO, "Enter memory test.\n")); } do { Status = GenMemoryTest->PerformMemoryTest ( GenMemoryTest, &TestedMemorySize, &TotalMemorySize, &ErrorOut, TestAbort ); if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } ASSERT (0); } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TempData = (UINT32) DivU64x32 (TotalMemorySize, 16); TestPercent = (UINTN) DivU64x32 ( DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), TempData ); if (TestPercent != PreviousValue) { UnicodeValueToString (StrPercent, 0, TestPercent, 0); TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); if (TmpStr != NULL) { // // TmpStr size is 64, StrPercent is reserved to 16. // StrnCatS ( StrPercent, sizeof (StrPercent) / sizeof (CHAR16), TmpStr, sizeof (StrPercent) / sizeof (CHAR16) - StrLen (StrPercent) - 1 ); PrintXY (10, 10, NULL, NULL, StrPercent); FreePool (TmpStr); } TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, TestPercent, (UINTN) PreviousValue ); FreePool (TmpStr); } } PreviousValue = TestPercent; } else { DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n")); } if (!PcdGetBool (PcdConInConnectOnDemand)) { KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) { if (!RequireSoftECCInit) { if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, 100, (UINTN) PreviousValue ); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, L"100"); } Status = GenMemoryTest->Finished (GenMemoryTest); goto Done; } TestAbort = TRUE; } } } while (Status != EFI_NOT_FOUND); Status = GenMemoryTest->Finished (GenMemoryTest); Done: if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0); if (StrTotalMemory[0] == L',') { StrTotalMemory++; StrTotalMemorySize -= sizeof (CHAR16); } TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); if (TmpStr != NULL) { StrnCatS ( StrTotalMemory, StrTotalMemorySize / sizeof (CHAR16), TmpStr, StrTotalMemorySize / sizeof (CHAR16) - StrLen (StrTotalMemory) - 1 ); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, StrTotalMemory); PlatformBdsShowProgress ( Foreground, Background, StrTotalMemory, Color, 100, (UINTN) PreviousValue ); } else { DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize)); } FreePool (Pos); // // Use a DynamicHii type pcd to save the boot status, which is used to // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration. // IsFirstBoot = PcdGetBool(PcdBootState); if (IsFirstBoot) { Status = PcdSetBoolS(PcdBootState, FALSE); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Set PcdBootState to FALSE failed.\n")); } } return ReturnStatus; }
/** Open the root directory on a volume. @param This A pointer to the volume to open the root directory. @param RootFile A pointer to the location to return the opened file handle for the root directory. @retval EFI_SUCCESS The device was opened. @retval EFI_UNSUPPORTED This volume does not support the requested file system type. @retval EFI_NO_MEDIA The device has no medium. @retval EFI_DEVICE_ERROR The device reported an error. @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. @retval EFI_ACCESS_DENIED The service denied access to the file. @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no longer supported. Any existing file handles for this volume are no longer valid. To access the files on the new medium, the volume must be reopened with OpenVolume(). **/ EFI_STATUS EFIAPI FvSimpleFileSystemOpenVolume ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, OUT EFI_FILE_PROTOCOL **RootFile ) { EFI_STATUS Status; FV_FILESYSTEM_FILE *Root; CHAR16 *UiSection; EFI_GUID NameGuid; EFI_FV_FILE_ATTRIBUTES Attributes; UINT32 Authentication; UINTN Key; EFI_FV_FILETYPE FileType; UINTN Size; FV_FILESYSTEM_INSTANCE *Instance; FV_FILESYSTEM_FILE_INFO *FvFileInfo; EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; CHAR16 *Name; UINTN NameLen; UINTN NumChars; UINTN DestMax; Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (This); Status = EFI_SUCCESS; if (Instance->Root == NULL) { // // Allocate file structure for root file // Root = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE)); if (Root == NULL) { return EFI_OUT_OF_RESOURCES; } Instance->Root = Root; Root->Instance = Instance; Root->Signature = FVFS_FILE_SIGNATURE; CopyMem (&Root->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate)); Root->FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO)); if (Root->FvFileInfo == NULL) { return EFI_OUT_OF_RESOURCES; } Root->FvFileInfo->FileInfo.Size = sizeof (EFI_FILE_INFO); Root->FvFileInfo->FileInfo.Attribute = EFI_FILE_DIRECTORY | EFI_FILE_READ_ONLY; // // Populate the instance's list of files. We consider anything a file that // has a UI_SECTION, which we consider to be its filename. // FvProtocol = Instance->FvProtocol; // // Allocate Key // Key = 0; do { FileType = EFI_FV_FILETYPE_ALL; Status = FvProtocol->GetNextFile ( FvProtocol, &Key, &FileType, &NameGuid, &Attributes, &Size ); if (EFI_ERROR (Status)) { ASSERT (Status == EFI_NOT_FOUND); break; } // // Get a file's name: If it has a UI section, use that, otherwise use // its NameGuid. // UiSection = NULL; Status = FvProtocol->ReadSection ( FvProtocol, &NameGuid, EFI_SECTION_USER_INTERFACE, 0, (VOID **)&UiSection, &Size, &Authentication ); if (!EFI_ERROR (Status)) { Name = UiSection; } else { Name = AllocateZeroPool (GUID_STRING_SIZE); if (Name == NULL) { return EFI_OUT_OF_RESOURCES; } NumChars = UnicodeSPrint (Name, GUID_STRING_SIZE, L"%g", &NameGuid); ASSERT ((NumChars + 1) * sizeof (CHAR16) == GUID_STRING_SIZE); } // // Found a file. // Allocate a file structure and populate it. // NameLen = StrSize (Name); if (FV_FILETYPE_IS_EXECUTABLE (FileType)) { NameLen += StrSize (L".efi") - sizeof (CHAR16); } FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO) + NameLen - sizeof (CHAR16)); if (FvFileInfo == NULL) { return EFI_OUT_OF_RESOURCES; } FvFileInfo->Signature = FVFS_FILE_INFO_SIGNATURE; InitializeListHead (&FvFileInfo->Link); CopyMem (&FvFileInfo->NameGuid, &NameGuid, sizeof (EFI_GUID)); FvFileInfo->Type = FileType; // // Add ".efi" to filenames of drivers and applications. // DestMax = NameLen / sizeof (CHAR16); Status = StrnCpyS (&FvFileInfo->FileInfo.FileName[0], DestMax, Name, StrLen (Name)); ASSERT_EFI_ERROR (Status); if (FV_FILETYPE_IS_EXECUTABLE (FileType)) { Status = StrnCatS (&FvFileInfo->FileInfo.FileName[0], DestMax, L".efi", StrLen (L".efi")); ASSERT_EFI_ERROR (Status); } FvFileInfo->FileInfo.Size = sizeof (EFI_FILE_INFO) + NameLen - sizeof (CHAR16); Status = FvFsGetFileSize (FvProtocol, FvFileInfo); ASSERT_EFI_ERROR (Status); FvFileInfo->FileInfo.PhysicalSize = FvFileInfo->FileInfo.FileSize; FvFileInfo->FileInfo.Attribute = EFI_FILE_READ_ONLY; InsertHeadList (&Instance->FileInfoHead, &FvFileInfo->Link); FreePool (Name); } while (TRUE); if (Status == EFI_NOT_FOUND) { Status = EFI_SUCCESS; } } Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance); *RootFile = &Instance->Root->FileProtocol; return Status; }
/** Safely append with automatic string resizing given length of Destination and desired length of copy from Source. append the first D characters of Source to the end of Destination, where D is the lesser of Count and the StrLen() of Source. If appending those D characters will fit within Destination (whose Size is given as CurrentSize) and still leave room for a NULL terminator, then those characters are appended, starting at the original terminating NULL of Destination, and a new terminating NULL is appended. If appending D characters onto Destination will result in a overflow of the size given in CurrentSize the string will be grown such that the copy can be performed and CurrentSize will be updated to the new size. If Source is NULL, there is nothing to append, just return the current buffer in Destination. if Destination is NULL, then ASSERT() if Destination's current length (including NULL terminator) is already more then CurrentSize, then ASSERT() @param[in, out] Destination The String to append onto @param[in, out] CurrentSize on call the number of bytes in Destination. On return possibly the new size (still in bytes). if NULL then allocate whatever is needed. @param[in] Source The String to append from @return Destination return the resultant string. **/ static CHAR16* InternalStrnCatGrow ( IN OUT CHAR16 **Destination, IN OUT UINTN *CurrentSize, IN CONST CHAR16 *Source ) { UINTN DestinationStartSize; UINTN NewSize; UINTN SourceLen; SourceLen = StrLen(Source); // // ASSERTs // ASSERT(Destination != NULL); // // If there's nothing to do then just return Destination // if (Source == NULL) { return (*Destination); } // // allow for un-initialized pointers, based on size being 0 // if (CurrentSize != NULL && *CurrentSize == 0) { *Destination = NULL; } // // allow for NULL pointers address as Destination // if (*Destination != NULL) { ASSERT(CurrentSize != 0); DestinationStartSize = StrSize(*Destination); ASSERT(DestinationStartSize <= *CurrentSize); } else { DestinationStartSize = 0; } // // Test and grow if required // if (CurrentSize != NULL) { NewSize = *CurrentSize; if (NewSize < DestinationStartSize + (SourceLen * sizeof(CHAR16))) { while (NewSize < (DestinationStartSize + (SourceLen*sizeof(CHAR16)))) { NewSize += 2 * SourceLen * sizeof(CHAR16); } *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination); *CurrentSize = NewSize; } } else { NewSize = (SourceLen + 1)*sizeof(CHAR16); *Destination = AllocateZeroPool(NewSize); } // // Now use standard StrnCat on a big enough buffer // if (*Destination == NULL) { return (NULL); } StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, SourceLen); return *Destination; }
/** Refresh the text mode page. @param CallbackData The BMM context data. **/ VOID UpdateConModePage ( IN BMM_CALLBACK_DATA *CallbackData ) { UINTN Mode; UINTN Index; UINTN Col; UINTN Row; CHAR16 ModeString[50]; CHAR16 *PStr; UINTN MaxMode; UINTN ValidMode; EFI_STRING_ID *ModeToken; EFI_STATUS Status; VOID *OptionsOpCodeHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; ConOut = gST->ConOut; Index = 0; ValidMode = 0; MaxMode = (UINTN) (ConOut->Mode->MaxMode); CallbackData->BmmAskSaveOrNot = TRUE; UpdatePageStart (CallbackData); // // Check valid mode // for (Mode = 0; Mode < MaxMode; Mode++) { Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); if (EFI_ERROR (Status)) { continue; } ValidMode++; } if (ValidMode == 0) { return; } OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (OptionsOpCodeHandle != NULL); ModeToken = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode); ASSERT(ModeToken != NULL); // // Determin which mode should be the first entry in menu // GetConsoleOutMode (CallbackData); // // Build text mode options // for (Mode = 0; Mode < MaxMode; Mode++) { Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); if (EFI_ERROR (Status)) { continue; } // // Build mode string Column x Row // UnicodeValueToString (ModeString, 0, Col, 0); PStr = &ModeString[0]; StrnCatS (PStr, sizeof (ModeString) / sizeof (ModeString[0]), L" x ", StrLen(L" x ") + 1); PStr = PStr + StrLen (PStr); UnicodeValueToString (PStr , 0, Row, 0); ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL); if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) { HiiCreateOneOfOptionOpCode ( OptionsOpCodeHandle, ModeToken[Index], EFI_IFR_OPTION_DEFAULT, EFI_IFR_TYPE_NUM_SIZE_16, (UINT16) Mode ); } else { HiiCreateOneOfOptionOpCode ( OptionsOpCodeHandle, ModeToken[Index], 0, EFI_IFR_TYPE_NUM_SIZE_16, (UINT16) Mode ); } Index++; } HiiCreateOneOfOpCode ( mStartOpCodeHandle, (EFI_QUESTION_ID) CON_MODE_QUESTION_ID, VARSTORE_ID_BOOT_MAINT, CON_MODE_VAR_OFFSET, STRING_TOKEN (STR_CON_MODE_SETUP), STRING_TOKEN (STR_CON_MODE_SETUP), EFI_IFR_FLAG_RESET_REQUIRED, EFI_IFR_NUMERIC_SIZE_2, OptionsOpCodeHandle, NULL ); HiiFreeOpCodeHandle (OptionsOpCodeHandle); FreePool (ModeToken); UpdatePageEnd (CallbackData); }