/** Internal function to add memory pool operation to the table. @param Marker The variable argument list to get the opcode and associated attributes. @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. @retval EFI_SUCCESS Opcode is added. **/ EFI_STATUS BootScriptMemPoll ( IN VA_LIST Marker ) { EFI_BOOT_SCRIPT_WIDTH Width; UINT64 Address; UINT8 *BitMask; UINT8 *BitValue; UINT64 Duration; UINT64 LoopTimes; UINT64 Delay; Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH); Address = VA_ARG (Marker, UINT64); BitMask = VA_ARG (Marker, UINT8 *); BitValue = VA_ARG (Marker, UINT8 *); Duration = (UINT64)VA_ARG (Marker, UINT64); LoopTimes = (UINT64)VA_ARG (Marker, UINT64); Delay = MultU64x64 (DivU64x32(Duration, 100), LoopTimes); return mS3SaveState->Write ( mS3SaveState, EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, Width, Address, BitMask, BitValue, Delay ); }
/** Initialize CPU local APIC timer. **/ VOID InitializeDebugTimer ( VOID ) { UINTN ApicTimerDivisor; UINT32 InitialCount; GetApicTimerState (&ApicTimerDivisor, NULL, NULL); // // Cpu Local Apic timer interrupt frequency, it is set to 0.1s // InitialCount = (UINT32)DivU64x32 ( MultU64x64 ( PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor, 100 ), 1000 ); InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR); if (MultiProcessorDebugSupport) { mDebugMpContext.DebugTimerInitCount = InitialCount; } }
/** Multiplies a 64-bit signed integer by a 64-bit signed integer and generates a 64-bit signed result. This function multiplies the 64-bit signed value Multiplicand by the 64-bit signed value Multiplier and generates a 64-bit signed result. This 64-bit signed result is returned. @param Multiplicand A 64-bit signed value. @param Multiplier A 64-bit signed value. @return Multiplicand * Multiplier. **/ INT64 EFIAPI MultS64x64 ( IN INT64 Multiplicand, IN INT64 Multiplier ) { return (INT64)MultU64x64 ((UINT64) Multiplicand, (UINT64) Multiplier); }
/** Stalls the CPU for at least the given number of nanoseconds. Stalls the CPU for the number of nanoseconds specified by NanoSeconds. @param NanoSeconds The minimum number of nanoseconds to delay. @return The value of NanoSeconds inputted. **/ UINTN EFIAPI NanoSecondDelay ( IN UINTN NanoSeconds ) { InternalX86Delay ( (UINT32)DivU64x32 ( MultU64x64 ( InternalX86GetTimerFrequency (), NanoSeconds ), 1000000000u ) ); return NanoSeconds; }
/** Internal function to add memory pool operation to the table. @param Marker The variable argument list to get the opcode and associated attributes. @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. @retval EFI_SUCCESS Opcode is added. **/ EFI_STATUS BootScriptMemPoll ( IN VA_LIST Marker ) { EFI_BOOT_SCRIPT_WIDTH Width; UINT64 Address; UINT8 *BitMask; UINT8 *BitValue; UINT64 Duration; UINT64 LoopTimes; UINT64 Delay; Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH); Address = VA_ARG (Marker, UINT64); BitMask = VA_ARG (Marker, UINT8 *); BitValue = VA_ARG (Marker, UINT8 *); Duration = (UINT64)VA_ARG (Marker, UINT64); LoopTimes = (UINT64)VA_ARG (Marker, UINT64); // // Framework version: Duration is used for Stall(), which is Microseconds. // Total time is: Duration(Microseconds) * LoopTimes. // PI version: Duration is always 100ns. Delay is LoopTimes. // Total time is: 100ns * Delay. // So Delay = Duration(Microseconds) * LoopTimes / 100ns // = Duration * 1000ns * LoopTimes / 100ns // = Duration * 10 * LoopTimes // Delay = MultU64x64 (MultU64x32 (Duration, 10), LoopTimes); // // Framework version: First BitMask, then BitValue // PI version: First Data, then DataMask // So we revert their order in function call // return mS3SaveState->Write ( mS3SaveState, EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, Width, Address, BitValue, BitMask, Delay ); }
/** Initialize CPU local APIC timer. @param[out] TimerFrequency Local APIC timer frequency returned. @param[in] DumpFlag If TRUE, dump Local APIC timer's parameter. @return 32-bit Local APIC timer init count. **/ UINT32 InitializeDebugTimer ( OUT UINT32 *TimerFrequency, IN BOOLEAN DumpFlag ) { UINTN ApicTimerDivisor; UINT32 InitialCount; UINT32 ApicTimerFrequency; InitializeLocalApicSoftwareEnable (TRUE); GetApicTimerState (&ApicTimerDivisor, NULL, NULL); ApicTimerFrequency = PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor; // // Cpu Local Apic timer interrupt frequency, it is set to 0.1s // InitialCount = (UINT32)DivU64x32 ( MultU64x64 ( ApicTimerFrequency, DEBUG_TIMER_INTERVAL ), 1000000u ); InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR); // // Disable Debug Timer interrupt to avoid it is delivered before Debug Port // is initialized // DisableApicTimerInterrupt (); if (DumpFlag) { DEBUG ((EFI_D_INFO, "Debug Timer: FSB Clock = %d\n", PcdGet32(PcdFSBClock))); DEBUG ((EFI_D_INFO, "Debug Timer: Divisor = %d\n", ApicTimerDivisor)); DEBUG ((EFI_D_INFO, "Debug Timer: Frequency = %d\n", ApicTimerFrequency)); DEBUG ((EFI_D_INFO, "Debug Timer: InitialCount = %d\n", InitialCount)); } if (TimerFrequency != NULL) { *TimerFrequency = ApicTimerFrequency; } return InitialCount; }
/** Stalls the CPU for at least the given number of nanoseconds. Stalls the CPU for the number of nanoseconds specified by NanoSeconds. @param NanoSeconds The minimum number of nanoseconds to delay. @return The value of NanoSeconds inputted. **/ UINTN EFIAPI NanoSecondDelay ( IN UINTN NanoSeconds ) { UINTN ApicBase; ApicBase = InternalX86GetApicBase (); InternalX86Delay ( ApicBase, (UINT32)DivU64x32 ( MultU64x64 ( InternalX86GetTimerFrequency (ApicBase), NanoSeconds ), 1000000000u ) ); return NanoSeconds; }
/** Initialize Timer for SMM AP Sync. **/ VOID InitializeSmmTimer ( VOID ) { UINT64 TimerFrequency; UINT64 Start; UINT64 End; TimerFrequency = GetPerformanceCounterProperties (&Start, &End); mTimeoutTicker = DivU64x32 ( MultU64x64(TimerFrequency, PcdGet64 (PcdCpuSmmApSyncTimeout)), 1000 * 1000 ); if (End < Start) { mCountDown = TRUE; mCycle = Start - End; } else { mCountDown = FALSE; mCycle = End - Start; } }
/** Initialize SMM profile data structures. **/ VOID InitSmmProfileInternal ( VOID ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Base; VOID *Registration; UINTN Index; UINTN MsrDsAreaSizePerCpu; UINTN TotalSize; mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mMaxNumberOfCpus); ASSERT (mPFEntryCount != NULL); mLastPFEntryValue = (UINT64 (*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool ( sizeof (mLastPFEntryValue[0]) * mMaxNumberOfCpus); ASSERT (mLastPFEntryValue != NULL); mLastPFEntryPointer = (UINT64 *(*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool ( sizeof (mLastPFEntryPointer[0]) * mMaxNumberOfCpus); ASSERT (mLastPFEntryPointer != NULL); // // Allocate memory for SmmProfile below 4GB. // The base address // mSmmProfileSize = PcdGet32 (PcdCpuSmmProfileSize); ASSERT ((mSmmProfileSize & 0xFFF) == 0); if (mBtsSupported) { TotalSize = mSmmProfileSize + mMsrDsAreaSize; } else { TotalSize = mSmmProfileSize; } Base = 0xFFFFFFFF; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (TotalSize), &Base ); ASSERT_EFI_ERROR (Status); ZeroMem ((VOID *)(UINTN)Base, TotalSize); mSmmProfileBase = (SMM_PROFILE_HEADER *)(UINTN)Base; // // Initialize SMM profile data header. // mSmmProfileBase->HeaderSize = sizeof (SMM_PROFILE_HEADER); mSmmProfileBase->MaxDataEntries = (UINT64)((mSmmProfileSize - sizeof(SMM_PROFILE_HEADER)) / sizeof (SMM_PROFILE_ENTRY)); mSmmProfileBase->MaxDataSize = MultU64x64 (mSmmProfileBase->MaxDataEntries, sizeof(SMM_PROFILE_ENTRY)); mSmmProfileBase->CurDataEntries = 0; mSmmProfileBase->CurDataSize = 0; mSmmProfileBase->TsegStart = mCpuHotPlugData.SmrrBase; mSmmProfileBase->TsegSize = mCpuHotPlugData.SmrrSize; mSmmProfileBase->NumSmis = 0; mSmmProfileBase->NumCpus = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; if (mBtsSupported) { mMsrDsArea = (MSR_DS_AREA_STRUCT **)AllocateZeroPool (sizeof (MSR_DS_AREA_STRUCT *) * mMaxNumberOfCpus); ASSERT (mMsrDsArea != NULL); mMsrBTSRecord = (BRANCH_TRACE_RECORD **)AllocateZeroPool (sizeof (BRANCH_TRACE_RECORD *) * mMaxNumberOfCpus); ASSERT (mMsrBTSRecord != NULL); mMsrPEBSRecord = (PEBS_RECORD **)AllocateZeroPool (sizeof (PEBS_RECORD *) * mMaxNumberOfCpus); ASSERT (mMsrPEBSRecord != NULL); mMsrDsAreaBase = (MSR_DS_AREA_STRUCT *)((UINTN)Base + mSmmProfileSize); MsrDsAreaSizePerCpu = mMsrDsAreaSize / mMaxNumberOfCpus; mBTSRecordNumber = (MsrDsAreaSizePerCpu - sizeof(PEBS_RECORD) * PEBS_RECORD_NUMBER - sizeof(MSR_DS_AREA_STRUCT)) / sizeof(BRANCH_TRACE_RECORD); for (Index = 0; Index < mMaxNumberOfCpus; Index++) { mMsrDsArea[Index] = (MSR_DS_AREA_STRUCT *)((UINTN)mMsrDsAreaBase + MsrDsAreaSizePerCpu * Index); mMsrBTSRecord[Index] = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[Index] + sizeof(MSR_DS_AREA_STRUCT)); mMsrPEBSRecord[Index] = (PEBS_RECORD *)((UINTN)mMsrDsArea[Index] + MsrDsAreaSizePerCpu - sizeof(PEBS_RECORD) * PEBS_RECORD_NUMBER); mMsrDsArea[Index]->BTSBufferBase = (UINTN)mMsrBTSRecord[Index]; mMsrDsArea[Index]->BTSIndex = mMsrDsArea[Index]->BTSBufferBase; mMsrDsArea[Index]->BTSAbsoluteMaximum = mMsrDsArea[Index]->BTSBufferBase + mBTSRecordNumber * sizeof(BRANCH_TRACE_RECORD) + 1; mMsrDsArea[Index]->BTSInterruptThreshold = mMsrDsArea[Index]->BTSAbsoluteMaximum + 1; mMsrDsArea[Index]->PEBSBufferBase = (UINTN)mMsrPEBSRecord[Index]; mMsrDsArea[Index]->PEBSIndex = mMsrDsArea[Index]->PEBSBufferBase; mMsrDsArea[Index]->PEBSAbsoluteMaximum = mMsrDsArea[Index]->PEBSBufferBase + PEBS_RECORD_NUMBER * sizeof(PEBS_RECORD) + 1; mMsrDsArea[Index]->PEBSInterruptThreshold = mMsrDsArea[Index]->PEBSAbsoluteMaximum + 1; } } mProtectionMemRange = mProtectionMemRangeTemplate; mProtectionMemRangeCount = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE); // // Update TSeg entry. // mProtectionMemRange[0].Range.Base = mCpuHotPlugData.SmrrBase; mProtectionMemRange[0].Range.Top = mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize; // // Update SMM profile entry. // mProtectionMemRange[1].Range.Base = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase; mProtectionMemRange[1].Range.Top = (EFI_PHYSICAL_ADDRESS)(UINTN)mSmmProfileBase + TotalSize; // // Allocate memory reserved for creating 4KB pages. // InitPagesForPFHandler (); // // Start SMM profile when SmmReadyToLock protocol is installed. // Status = gSmst->SmmRegisterProtocolNotify ( &gEfiSmmReadyToLockProtocolGuid, InitSmmProfileCallBack, &Registration ); ASSERT_EFI_ERROR (Status); return ; }
/** The Page fault handler to save SMM profile data. @param Rip The RIP when exception happens. @param ErrorCode The Error code of exception. **/ VOID SmmProfilePFHandler ( UINTN Rip, UINTN ErrorCode ) { UINT64 *PageTable; UINT64 PFAddress; UINTN CpuIndex; UINTN Index; UINT64 InstructionAddress; UINTN MaxEntryNumber; UINTN CurrentEntryNumber; BOOLEAN IsValidPFAddress; SMM_PROFILE_ENTRY *SmmProfileEntry; UINT64 SmiCommand; EFI_STATUS Status; UINT8 SoftSmiValue; EFI_SMM_SAVE_STATE_IO_INFO IoInfo; if (!mSmmProfileStart) { // // If SMM profile does not start, call original page fault handler. // SmiDefaultPFHandler (); return; } if (mBtsSupported) { DisableBTS (); } IsValidPFAddress = FALSE; PageTable = (UINT64 *)AsmReadCr3 (); PFAddress = AsmReadCr2 (); CpuIndex = GetCpuIndex (); if (PFAddress <= 0xFFFFFFFF) { RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode); } else { RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress); } if (!IsValidPFAddress) { InstructionAddress = Rip; if ((ErrorCode & IA32_PF_EC_ID) != 0 && (mBtsSupported)) { // // If it is instruction fetch failure, get the correct IP from BTS. // InstructionAddress = GetSourceFromDestinationOnBts (CpuIndex, Rip); if (InstructionAddress == 0) { // // It indicates the instruction which caused page fault is not a jump instruction, // set instruction address same as the page fault address. // InstructionAddress = PFAddress; } } // // Indicate it is not software SMI // SmiCommand = 0xFFFFFFFFFFFFFFFFULL; for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { Status = SmmReadSaveState(&mSmmCpu, sizeof(IoInfo), EFI_SMM_SAVE_STATE_REGISTER_IO, Index, &IoInfo); if (EFI_ERROR (Status)) { continue; } if (IoInfo.IoPort == mSmiCommandPort) { // // A software SMI triggered by SMI command port has been found, get SmiCommand from SMI command port. // SoftSmiValue = IoRead8 (mSmiCommandPort); SmiCommand = (UINT64)SoftSmiValue; break; } } SmmProfileEntry = (SMM_PROFILE_ENTRY *)(UINTN)(mSmmProfileBase + 1); // // Check if there is already a same entry in profile data. // for (Index = 0; Index < (UINTN) mSmmProfileBase->CurDataEntries; Index++) { if ((SmmProfileEntry[Index].ErrorCode == (UINT64)ErrorCode) && (SmmProfileEntry[Index].Address == PFAddress) && (SmmProfileEntry[Index].CpuNum == (UINT64)CpuIndex) && (SmmProfileEntry[Index].Instruction == InstructionAddress) && (SmmProfileEntry[Index].SmiCmd == SmiCommand)) { // // Same record exist, need not save again. // break; } } if (Index == mSmmProfileBase->CurDataEntries) { CurrentEntryNumber = (UINTN) mSmmProfileBase->CurDataEntries; MaxEntryNumber = (UINTN) mSmmProfileBase->MaxDataEntries; if (FeaturePcdGet (PcdCpuSmmProfileRingBuffer)) { CurrentEntryNumber = CurrentEntryNumber % MaxEntryNumber; } if (CurrentEntryNumber < MaxEntryNumber) { // // Log the new entry // SmmProfileEntry[CurrentEntryNumber].SmiNum = mSmmProfileBase->NumSmis; SmmProfileEntry[CurrentEntryNumber].ErrorCode = (UINT64)ErrorCode; SmmProfileEntry[CurrentEntryNumber].ApicId = (UINT64)GetApicId (); SmmProfileEntry[CurrentEntryNumber].CpuNum = (UINT64)CpuIndex; SmmProfileEntry[CurrentEntryNumber].Address = PFAddress; SmmProfileEntry[CurrentEntryNumber].Instruction = InstructionAddress; SmmProfileEntry[CurrentEntryNumber].SmiCmd = SmiCommand; // // Update current entry index and data size in the header. // mSmmProfileBase->CurDataEntries++; mSmmProfileBase->CurDataSize = MultU64x64 (mSmmProfileBase->CurDataEntries, sizeof (SMM_PROFILE_ENTRY)); } } } // // Flush TLB // CpuFlushTlb (); if (mBtsSupported) { EnableBTS (); } }
/** Function for 'memmap' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunMemMap ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; UINTN Size; EFI_MEMORY_DESCRIPTOR *Buffer; UINTN MapKey; UINTN ItemSize; UINT32 Version; UINT8 *Walker; UINT64 ReservedPages; UINT64 LoadCodePages; UINT64 LoadDataPages; UINT64 BSCodePages; UINT64 BSDataPages; UINT64 RTDataPages; UINT64 RTCodePages; UINT64 AvailPages; UINT64 TotalPages; UINT64 ReservedPagesSize; UINT64 LoadCodePagesSize; UINT64 LoadDataPagesSize; UINT64 BSCodePagesSize; UINT64 BSDataPagesSize; UINT64 RTDataPagesSize; UINT64 RTCodePagesSize; UINT64 AvailPagesSize; UINT64 TotalPagesSize; UINT64 AcpiReclaimPages; UINT64 AcpiNvsPages; UINT64 MmioSpacePages; UINT64 AcpiReclaimPagesSize; UINT64 AcpiNvsPagesSize; UINT64 MmioSpacePagesSize; UINT64 MmioPortPages; UINT64 MmioPortPagesSize; UINT64 UnusableMemoryPages; UINT64 UnusableMemoryPagesSize; UINT64 PalCodePages; UINT64 PalCodePagesSize; BOOLEAN Sfo; AcpiReclaimPages = 0; AcpiNvsPages = 0; MmioSpacePages = 0; TotalPages = 0; ReservedPages = 0; LoadCodePages = 0; LoadDataPages = 0; BSCodePages = 0; BSDataPages = 0; RTDataPages = 0; RTCodePages = 0; AvailPages = 0; MmioPortPages = 0; UnusableMemoryPages = 0; PalCodePages = 0; Size = 0; Buffer = NULL; ShellStatus = SHELL_SUCCESS; Status = EFI_SUCCESS; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); ASSERT_EFI_ERROR(Status); Status = CommandInit(); ASSERT_EFI_ERROR(Status); // // parse the command line // Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT(FALSE); } } else { if (ShellCommandLineGetCount(Package) > 1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; } else { Status = gBS->GetMemoryMap(&Size, Buffer, &MapKey, &ItemSize, &Version); if (Status == EFI_BUFFER_TOO_SMALL){ Size += SIZE_1KB; Buffer = AllocateZeroPool(Size); Status = gBS->GetMemoryMap(&Size, Buffer, &MapKey, &ItemSize, &Version); } if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_GET_FAILED), gShellDebug1HiiHandle, Status); ShellStatus = SHELL_ACCESS_DENIED; } else { ASSERT(Version == EFI_MEMORY_DESCRIPTOR_VERSION); Sfo = ShellCommandLineGetFlag(Package, L"-sfo"); if (!Sfo) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_HEAD), gShellDebug1HiiHandle); } else { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDebug1HiiHandle, L"memmap"); } for (Walker = (UINT8*)Buffer; Walker < (((UINT8*)Buffer)+Size) && Walker != NULL; Walker += ItemSize){ switch (((EFI_MEMORY_DESCRIPTOR*)Walker)->Type) { case EfiReservedMemoryType: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiReservedMemoryType, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); ReservedPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiLoaderCode: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiLoaderCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); LoadCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiLoaderData: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiLoaderData, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); LoadDataPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiBootServicesCode: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiBootServicesCodeShort:NameEfiBootServicesCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); BSCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiBootServicesData: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiBootServicesDataShort:NameEfiBootServicesData, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); BSDataPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiRuntimeServicesCode: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiRuntimeServicesCodeShort:NameEfiRuntimeServicesCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); RTCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiRuntimeServicesData: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiRuntimeServicesDataShort:NameEfiRuntimeServicesData, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); RTDataPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiConventionalMemory: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiConventionalMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); AvailPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiUnusableMemory: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiUnusableMemoryShort:NameEfiUnusableMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); UnusableMemoryPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiACPIReclaimMemory: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiACPIReclaimMemoryShort:NameEfiACPIReclaimMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; AcpiReclaimPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiACPIMemoryNVS: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiACPIMemoryNVSShort:NameEfiACPIMemoryNVS, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; AcpiNvsPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiMemoryMappedIO: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiMemoryMappedIOShort:NameEfiMemoryMappedIO, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); MmioSpacePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiMemoryMappedIOPortSpace: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiMemoryMappedIOPortSpaceShort:NameEfiMemoryMappedIOPortSpace, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); MmioPortPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; case EfiPalCode: ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiPalCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute); TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; PalCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages; break; default: ASSERT(FALSE); } } // // print the summary // ReservedPagesSize = MultU64x64(SIZE_4KB,ReservedPages); LoadCodePagesSize = MultU64x64(SIZE_4KB,LoadCodePages); LoadDataPagesSize = MultU64x64(SIZE_4KB,LoadDataPages); BSCodePagesSize = MultU64x64(SIZE_4KB,BSCodePages); BSDataPagesSize = MultU64x64(SIZE_4KB,BSDataPages); RTDataPagesSize = MultU64x64(SIZE_4KB,RTDataPages); RTCodePagesSize = MultU64x64(SIZE_4KB,RTCodePages); AvailPagesSize = MultU64x64(SIZE_4KB,AvailPages); TotalPagesSize = MultU64x64(SIZE_4KB,TotalPages); AcpiReclaimPagesSize = MultU64x64(SIZE_4KB,AcpiReclaimPages); AcpiNvsPagesSize = MultU64x64(SIZE_4KB,AcpiNvsPages); MmioSpacePagesSize = MultU64x64(SIZE_4KB,MmioSpacePages); MmioPortPagesSize = MultU64x64(SIZE_4KB,MmioPortPages); PalCodePagesSize = MultU64x64(SIZE_4KB,PalCodePages); UnusableMemoryPagesSize = MultU64x64(SIZE_4KB,UnusableMemoryPages); if (!Sfo) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM), gShellDebug1HiiHandle, ReservedPages, ReservedPagesSize, LoadCodePages, LoadCodePagesSize, LoadDataPages, LoadDataPagesSize, BSCodePages, BSCodePagesSize, BSDataPages, BSDataPagesSize, RTCodePages, RTCodePagesSize, RTDataPages, RTDataPagesSize, AcpiReclaimPages, AcpiReclaimPagesSize, AcpiNvsPages, AcpiNvsPagesSize, MmioSpacePages, MmioSpacePagesSize, MmioPortPages, MmioPortPagesSize, PalCodePages, PalCodePagesSize, AvailPages, AvailPagesSize, DivU64x32(MultU64x64(SIZE_4KB,TotalPages), SIZE_1MB), TotalPagesSize ); } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM_SFO), gShellDebug1HiiHandle, TotalPagesSize, ReservedPagesSize, BSCodePagesSize, BSDataPagesSize, RTCodePagesSize, RTDataPagesSize, LoadCodePagesSize, LoadDataPagesSize, AvailPagesSize, MmioSpacePagesSize, MmioPortPagesSize, UnusableMemoryPagesSize, AcpiReclaimPagesSize, AcpiNvsPagesSize, PalCodePagesSize ); } } } ShellCommandLineFreeVarList (Package); } if (Buffer != NULL) { FreePool(Buffer); } return (ShellStatus); }
/** Use SystemTable Conout to stop video based Simple Text Out consoles from going to the video device. Put up LogoFile on every video device that is a console. @param[in] LogoFile File name of logo to display on the center of the screen. @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. @retval EFI_UNSUPPORTED Logo not found **/ EFI_STATUS EFIAPI EnableQuietBoot ( IN EFI_GUID *LogoFile ) { EFI_STATUS Status; EFI_OEM_BADGING_PROTOCOL *Badging; UINT32 SizeOfX; UINT32 SizeOfY; INTN DestX; INTN DestY; UINT8 *ImageData; UINTN ImageSize; UINTN BltSize; UINT32 Instance; EFI_BADGING_FORMAT Format; EFI_BADGING_DISPLAY_ATTRIBUTE Attribute; UINTN CoordinateX; UINTN CoordinateY; UINTN Height; UINTN Width; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; EFI_UGA_DRAW_PROTOCOL *UgaDraw; UINT32 ColorDepth; UINT32 RefreshRate; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; EFI_BOOT_LOGO_PROTOCOL *BootLogo; UINTN NumberOfLogos; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt; UINTN LogoDestX; UINTN LogoDestY; UINTN LogoHeight; UINTN LogoWidth; UINTN NewDestX; UINTN NewDestY; UINTN NewHeight; UINTN NewWidth; UINT64 BufferSize; UgaDraw = NULL; // // Try to open GOP first // Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput); if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { GraphicsOutput = NULL; // // Open GOP failed, try to open UGA // Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw); } if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } // // Try to open Boot Logo Protocol. // BootLogo = NULL; gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); // // Erase Cursor from screen // gST->ConOut->EnableCursor (gST->ConOut, FALSE); Badging = NULL; Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging); if (GraphicsOutput != NULL) { SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } } else { return EFI_UNSUPPORTED; } Blt = NULL; NumberOfLogos = 0; LogoDestX = 0; LogoDestY = 0; LogoHeight = 0; LogoWidth = 0; NewDestX = 0; NewDestY = 0; NewHeight = 0; NewWidth = 0; Instance = 0; while (1) { ImageData = NULL; ImageSize = 0; if (Badging != NULL) { // // Get image from OEMBadging protocol. // Status = Badging->GetImage ( Badging, &Instance, &Format, &ImageData, &ImageSize, &Attribute, &CoordinateX, &CoordinateY ); if (EFI_ERROR (Status)) { goto Done; } // // Currently only support BMP format. // if (Format != EfiBadgingFormatBMP) { if (ImageData != NULL) { FreePool (ImageData); } continue; } } else { // // Get the specified image from FV. // Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } CoordinateX = 0; CoordinateY = 0; if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { Attribute = EfiBadgingDisplayAttributeCenter; } else { Attribute = EfiBadgingDisplayAttributeCustomized; } } if (Blt != NULL) { FreePool (Blt); } Blt = NULL; Status = TranslateBmpToGopBlt ( ImageData, ImageSize, &Blt, &BltSize, &Height, &Width ); if (EFI_ERROR (Status)) { FreePool (ImageData); if (Badging == NULL) { return Status; } else { continue; } } // // Calculate the display position according to Attribute. // switch (Attribute) { case EfiBadgingDisplayAttributeLeftTop: DestX = CoordinateX; DestY = CoordinateY; break; case EfiBadgingDisplayAttributeCenterTop: DestX = (SizeOfX - Width) / 2; DestY = CoordinateY; break; case EfiBadgingDisplayAttributeRightTop: DestX = (SizeOfX - Width - CoordinateX); DestY = CoordinateY;; break; case EfiBadgingDisplayAttributeCenterRight: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeRightBottom: DestX = (SizeOfX - Width - CoordinateX); DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeCenterBottom: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeLeftBottom: DestX = CoordinateX; DestY = (SizeOfY - Height - CoordinateY); break; case EfiBadgingDisplayAttributeCenterLeft: DestX = CoordinateX; DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeCenter: DestX = (SizeOfX - Width) / 2; DestY = (SizeOfY - Height) / 2; break; case EfiBadgingDisplayAttributeCustomized: DestX = (SizeOfX - Width) / 2; DestY = ((SizeOfY * 382) / 1000) - Height / 2; break; default: DestX = CoordinateX; DestY = CoordinateY; break; } if ((DestX >= 0) && (DestY >= 0)) { if (GraphicsOutput != NULL) { Status = GraphicsOutput->Blt ( GraphicsOutput, Blt, EfiBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) Blt, EfiUgaBltBufferToVideo, 0, 0, (UINTN) DestX, (UINTN) DestY, Width, Height, Width * sizeof (EFI_UGA_PIXEL) ); } else { Status = EFI_UNSUPPORTED; } // // Report displayed Logo information. // if (!EFI_ERROR (Status)) { NumberOfLogos++; if (LogoWidth == 0) { // // The first Logo. // LogoDestX = (UINTN) DestX; LogoDestY = (UINTN) DestY; LogoWidth = Width; LogoHeight = Height; } else { // // Merge new logo with old one. // NewDestX = MIN ((UINTN) DestX, LogoDestX); NewDestY = MIN ((UINTN) DestY, LogoDestY); NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX; NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY; LogoDestX = NewDestX; LogoDestY = NewDestY; LogoWidth = NewWidth; LogoHeight = NewHeight; } } } FreePool (ImageData); if (Badging == NULL) { break; } } Done: if (BootLogo == NULL || NumberOfLogos == 0) { // // No logo displayed. // if (Blt != NULL) { FreePool (Blt); } return Status; } // // Advertise displayed Logo information. // if (NumberOfLogos == 1) { // // Only one logo displayed, use its Blt buffer directly for BootLogo protocol. // LogoBlt = Blt; Status = EFI_SUCCESS; } else { // // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. // if (Blt != NULL) { FreePool (Blt); } // // Ensure the LogoHeight * LogoWidth doesn't overflow // if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) { return EFI_UNSUPPORTED; } BufferSize = MultU64x64 (LogoWidth, LogoHeight); // // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow // if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { return EFI_UNSUPPORTED; } LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); if (LogoBlt == NULL) { return EFI_OUT_OF_RESOURCES; } if (GraphicsOutput != NULL) { Status = GraphicsOutput->Blt ( GraphicsOutput, LogoBlt, EfiBltVideoToBltBuffer, LogoDestX, LogoDestY, 0, 0, LogoWidth, LogoHeight, LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { Status = UgaDraw->Blt ( UgaDraw, (EFI_UGA_PIXEL *) LogoBlt, EfiUgaVideoToBltBuffer, LogoDestX, LogoDestY, 0, 0, LogoWidth, LogoHeight, LogoWidth * sizeof (EFI_UGA_PIXEL) ); } else { Status = EFI_UNSUPPORTED; } } if (!EFI_ERROR (Status)) { BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight); } FreePool (LogoBlt); return Status; }
/** Read data from debug device and save the datas in buffer. Reads NumberOfBytes data bytes from a debug device into the buffer specified by Buffer. The number of bytes actually read is returned. If the return value is less than NumberOfBytes, then the rest operation failed. If NumberOfBytes is zero, then return 0. @param Handle Debug port handle. @param Buffer Pointer to the data buffer to store the data read from the debug device. @param NumberOfBytes Number of bytes which will be read. @param Timeout Timeout value for reading from debug device. It unit is Microsecond. @retval 0 Read data failed, no data is to be read. @retval >0 Actual number of bytes read from debug device. **/ UINTN EFIAPI DebugPortReadBuffer ( IN DEBUG_PORT_HANDLE Handle, IN UINT8 *Buffer, IN UINTN NumberOfBytes, IN UINTN Timeout ) { USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle; USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister; RETURN_STATUS Status; UINT8 Received; UINTN Total; UINTN Remaining; UINT8 Index; UINT8 Length; UINT64 Begin; UINT64 TimeoutTicker; UINT64 TimerRound; if (NumberOfBytes == 0 || Buffer == NULL) { return 0; } Received = 0; Total = 0; Remaining = 0; // // If Handle is NULL, it means memory is ready for use. // Use global variable to store handle value. // if (Handle == NULL) { UsbDebugPortHandle = &mUsbDebugPortHandle; } else { UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle; } if (NeedReinitializeHardware(UsbDebugPortHandle)) { Status = InitializeUsbDebugHardware (UsbDebugPortHandle); if (RETURN_ERROR(Status)) { return 0; } } UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset); // // First read data from buffer, then read debug port hw to get received data. // if (UsbDebugPortHandle->DataCount > 0) { if (NumberOfBytes <= UsbDebugPortHandle->DataCount) { Total = NumberOfBytes; } else { Total = UsbDebugPortHandle->DataCount; } for (Index = 0; Index < Total; Index++) { Buffer[Index] = UsbDebugPortHandle->Data[Index]; } for (Index = 0; Index < UsbDebugPortHandle->DataCount - Total; Index++) { if (Total + Index >= 8) { return 0; } UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Total + Index]; } UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total); } // // If Timeout is equal to 0, then it means it should always wait until all datum required are received. // Begin = 0; TimeoutTicker = 0; TimerRound = 0; if (Timeout != 0) { Begin = GetPerformanceCounter (); TimeoutTicker = DivU64x32 ( MultU64x64 ( UsbDebugPortHandle->TimerFrequency, Timeout ), 1000000u ); TimerRound = DivU64x64Remainder ( TimeoutTicker, DivU64x32 (UsbDebugPortHandle->TimerCycle, 2), &TimeoutTicker ); } // // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw. // while (Total < NumberOfBytes) { if (Timeout != 0) { if (TimerRound == 0) { if (IsTimerTimeout (UsbDebugPortHandle, Begin, TimeoutTicker)) { // // If time out occurs. // return 0; } } else { if (IsTimerTimeout (UsbDebugPortHandle, Begin, DivU64x32 (UsbDebugPortHandle->TimerCycle, 2))) { TimerRound --; } } } Remaining = NumberOfBytes - Total; if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) { Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle); if (RETURN_ERROR(Status)) { return Total; } } else { Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle); if (RETURN_ERROR(Status)) { return Total; } UsbDebugPortHandle->DataCount = Received; if (Remaining <= Received) { Length = (UINT8)Remaining; } else { Length = (UINT8)Received; } // // Copy required data from the data buffer to user buffer. // for (Index = 0; Index < Length; Index++) { (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index]; UsbDebugPortHandle->DataCount--; } // // reorder the data buffer to make available data arranged from the beginning of the data buffer. // for (Index = 0; Index < Received - Length; Index++) { if (Length + Index >= 8) { return 0; } UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index]; } // // fixup the real received length in Buffer. // Received = Length; } UsbDebugPortHandle->BulkInToggle ^= 1; Total += Received; } return Total; }