/** Produce current time as ascii text string @retval pointer to statuc buffer with current time or zero length string **/ CHAR8* GetTiming(VOID) { UINT64 dTStartSec; UINT64 dTStartMs; UINT64 dTLastSec; UINT64 dTLastMs; UINT64 CurrentTsc; mTimingTxt[0] = '\0'; if (mMemLog != NULL && mMemLog->TscFreqSec != 0) { CurrentTsc = AsmReadTsc(); dTStartMs = DivU64x64Remainder(MultU64x32(CurrentTsc - mMemLog->TscStart, 1000), mMemLog->TscFreqSec, NULL); dTStartSec = DivU64x64Remainder(dTStartMs, 1000, &dTStartMs); dTLastMs = DivU64x64Remainder(MultU64x32(CurrentTsc - mMemLog->TscLast, 1000), mMemLog->TscFreqSec, NULL); dTLastSec = DivU64x64Remainder(dTLastMs, 1000, &dTLastMs); AsciiSPrint(mTimingTxt, sizeof(mTimingTxt), "%ld:%03ld %ld:%03ld", dTStartSec, dTStartMs, dTLastSec, dTLastMs); mMemLog->TscLast = CurrentTsc; } return mTimingTxt; }
/** This function attempts to set the attributes for a memory range. @param BaseAddress The physical address that is the start address of a memory region. @param Length The size in bytes of the memory region. @param Attributes The bit mask of attributes to set for the memory region. @retval RETURN_SUCCESS The attributes were set for the memory region. @retval RETURN_INVALID_PARAMETER Length is zero. @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory resource range specified by BaseAddress and Length. @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource range specified by BaseAddress and Length. @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of the memory resource range. **/ RETURN_STATUS EFIAPI MtrrSetMemoryAttribute ( IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN MTRR_MEMORY_CACHE_TYPE Attribute ) { UINT64 TempQword; RETURN_STATUS Status; UINT64 MemoryType; UINT64 Remainder; BOOLEAN OverLap; BOOLEAN Positive; UINT32 MsrNum; UINTN MtrrNumber; VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; UINT32 UsedMtrr; UINT64 MtrrValidBitsMask; UINT64 MtrrValidAddressMask; UINTN Cr4; BOOLEAN OverwriteExistingMtrr; UINT32 FirmwareVariableMtrrCount; UINT32 VariableMtrrEnd; if (!IsMtrrSupported ()) { return RETURN_UNSUPPORTED; } FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount (); VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1; MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask); TempQword = 0; MemoryType = (UINT64)Attribute; OverwriteExistingMtrr = FALSE; // // Check for an invalid parameter // if (Length == 0) { return RETURN_INVALID_PARAMETER; } if ( (BaseAddress &~MtrrValidAddressMask) != 0 || (Length &~MtrrValidAddressMask) != 0 ) { return RETURN_UNSUPPORTED; } // // Check if Fixed MTRR // Status = RETURN_SUCCESS; while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) { Cr4 = PreMtrrChange (); Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length); PostMtrrChange (Cr4); if (RETURN_ERROR (Status)) { return Status; } } if (Length == 0) { // // A Length of 0 can only make sense for fixed MTTR ranges. // Since we just handled the fixed MTRRs, we can skip the // variable MTRR section. // goto Done; } // // Since memory ranges below 1MB will be overridden by the fixed MTRRs, // we can set the bade to 0 to save variable MTRRs. // if (BaseAddress == BASE_1MB) { BaseAddress = 0; Length += SIZE_1MB; } // // Check memory base address alignment // DivU64x64Remainder (BaseAddress, Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder); if (Remainder != 0) { DivU64x64Remainder (BaseAddress, Power2MaxMemory (Length), &Remainder); if (Remainder != 0) { Status = RETURN_UNSUPPORTED; goto Done; } } // // Check for overlap // UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr); OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr); if (OverLap) { Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr); if (RETURN_ERROR (Status)) { goto Done; } if (Length == 0) { // // Combined successfully // Status = RETURN_SUCCESS; goto Done; } } // // Program Variable MTRRs // // Avoid hardcode here and read data dynamically // if (UsedMtrr >= FirmwareVariableMtrrCount) { Status = RETURN_OUT_OF_RESOURCES; goto Done; } // // The memory type is the same with the type specified by // MTRR_LIB_IA32_MTRR_DEF_TYPE. // if ((!OverwriteExistingMtrr) && (Attribute == GetMtrrDefaultMemoryType ())) { // // Invalidate the now-unused MTRRs // InvalidateMtrr(VariableMtrr); goto Done; } TempQword = Length; if (TempQword == Power2MaxMemory (TempQword)) { // // Invalidate the now-unused MTRRs // InvalidateMtrr(VariableMtrr); // // Find first unused MTRR // for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE; MsrNum < VariableMtrrEnd; MsrNum += 2 ) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); } else { Positive = GetDirection (TempQword, &MtrrNumber); if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) { Status = RETURN_OUT_OF_RESOURCES; goto Done; } // // Invalidate the now-unused MTRRs // InvalidateMtrr(VariableMtrr); // // Find first unused MTRR // for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE; MsrNum < VariableMtrrEnd; MsrNum += 2 ) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } if (!Positive) { Length = Power2MaxMemory (LShiftU64 (TempQword, 1)); ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); BaseAddress += Length; TempQword = Length - TempQword; MemoryType = MTRR_CACHE_UNCACHEABLE; } do { // // Find unused MTRR // for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } Length = Power2MaxMemory (TempQword); if (!Positive) { BaseAddress -= Length; } ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); if (Positive) { BaseAddress += Length; } TempQword -= Length; } while (TempQword > 0); } Done: return Status; }
UINT8 smb_read_byte(UINT32 base, UINT8 adr, UINT8 cmd) { // INTN l1, h1, l2, h2; UINT64 t, t1, t2; if (smbIntel) { IoWrite8(base + SMBHSTSTS, 0x1f); // reset SMBus Controller IoWrite8(base + SMBHSTDAT, 0xff); t1 = AsmReadTsc(); //rdtsc(l1, h1); while ( IoRead8(base + SMBHSTSTS) & 0x01) // wait until read { t2 = AsmReadTsc(); //rdtsc(l2, h2); t = DivU64x64Remainder((t2 - t1), DivU64x32(gCPUStructure.TSCFrequency, 1000), 0); if (t > 5) return 0xFF; // break } IoWrite8(base + SMBHSTCMD, cmd); IoWrite8(base + SMBHSTADD, (adr << 1) | 0x01 ); IoWrite8(base + SMBHSTCNT, 0x48 ); t1 = AsmReadTsc(); while (!( IoRead8(base + SMBHSTSTS) & 0x02)) // wait til command finished { t2 = AsmReadTsc(); t = DivU64x64Remainder((t2 - t1), DivU64x32(gCPUStructure.TSCFrequency, 1000), 0); if (t > 5) break; // break after 5ms } return IoRead8(base + SMBHSTDAT); } else { IoWrite8(base + SMBHSTSTS_NV, 0x1f); // reset SMBus Controller IoWrite8(base + SMBHSTDAT_NV, 0xff); t1 = AsmReadTsc(); //rdtsc(l1, h1); while ( IoRead8(base + SMBHSTSTS_NV) & 0x01) // wait until read { t2 = AsmReadTsc(); //rdtsc(l2, h2); t = DivU64x64Remainder((t2 - t1), DivU64x32(gCPUStructure.TSCFrequency, 1000), 0); if (t > 5) return 0xFF; // break } IoWrite8(base + SMBHSTSTS_NV, 0x00); // clear status register IoWrite8(base + SMBHSTCMD_NV, cmd); IoWrite8(base + SMBHSTADD_NV, (adr << 1) | 0x01 ); IoWrite8(base + SMBHPRTCL_NV, 0x07 ); t1 = AsmReadTsc(); while (!( IoRead8(base + SMBHSTSTS_NV) & 0x9F)) // wait till command finished { t2 = AsmReadTsc(); t = DivU64x64Remainder((t2 - t1), DivU64x32(gCPUStructure.TSCFrequency, 1000), 0); if (t > 5) break; // break after 5ms } return IoRead8(base + SMBHSTDAT_NV); } }
/** Create PRP lists for Data transfer which is larger than 2 memory pages. @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure. @param[in] PhysicalAddr The physical base address of Data Buffer. @param[in] Pages The number of pages to be transfered. @retval The pointer Value to the first PRP List of the PRP lists. **/ UINT64 NvmeCreatePrpList ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private, IN EFI_PHYSICAL_ADDRESS PhysicalAddr, IN UINTN Pages ) { UINTN PrpEntryNo; UINTN PrpListNo; UINT64 PrpListBase; VOID *PrpListHost; UINTN PrpListIndex; UINTN PrpEntryIndex; UINT64 Remainder; EFI_PHYSICAL_ADDRESS PrpListPhyAddr; UINTN Bytes; UINT8 *PrpEntry; EFI_PHYSICAL_ADDRESS NewPhyAddr; // // The number of Prp Entry in a memory page. // PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64); // // Calculate total PrpList number. // PrpListNo = (UINTN) DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo, &Remainder); if (Remainder != 0) { PrpListNo += 1; } if (PrpListNo > NVME_PRP_SIZE) { DEBUG (( DEBUG_ERROR, "%a: The implementation only supports PrpList number up to 4." " But %d are needed here.\n", __FUNCTION__, PrpListNo )); return 0; } PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Private); Bytes = EFI_PAGES_TO_SIZE (PrpListNo); PrpListPhyAddr = (UINT64)(UINTN)(PrpListHost); // // Fill all PRP lists except of last one. // ZeroMem (PrpListHost, Bytes); for (PrpListIndex = 0; PrpListIndex < PrpListNo - 1; ++PrpListIndex) { PrpListBase = (UINTN)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) { PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64)); if (PrpEntryIndex != PrpEntryNo - 1) { // // Fill all PRP entries except of last one. // CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64)); PhysicalAddr += EFI_PAGE_SIZE; } else { // // Fill last PRP entries with next PRP List pointer. // NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE); CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof (UINT64)); } } } // // Fill last PRP list. // PrpListBase = (UINTN)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder : PrpEntryNo); ++PrpEntryIndex) { PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64)); CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64)); PhysicalAddr += EFI_PAGE_SIZE; } return PrpListPhyAddr; }
extern "C" UINT64 _aulldiv(UINT64 sm1, UINT64 sm2) { return DivU64x64Remainder(sm1, sm2, NULL); }
/** 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; }
/** Simple arm disassembler via a library Argv[0] - disasm Argv[1] - Address to start disassembling from ARgv[2] - Number of instructions to disassembly (optional) @param Argc Number of command arguments in Argv @param Argv Array of strings that represent the parsed command line. Argv[0] is the command name @return EFI_SUCCESS **/ EFI_STATUS EblPerformance ( IN UINTN Argc, IN CHAR8 **Argv ) { UINTN Key; CONST VOID *Handle; CONST CHAR8 *Token, *Module; UINT64 Start, Stop, TimeStamp; UINT64 Delta, TicksPerSecond, Milliseconds, Microseconds; UINTN Index; BOOLEAN CountUp; TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop); if (Start < Stop) { CountUp = TRUE; } else { CountUp = FALSE; } Key = 0; do { Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop); if (Key != 0) { if (AsciiStriCmp ("StartImage:", Token) == 0) { if (Stop == 0) { // The entry for EBL is still running so the stop time will be zero. Skip it AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle)); } else { Delta = CountUp?(Stop - Start):(Start - Stop); Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL); AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle)); } } } } while (Key != 0); AsciiPrint ("\n"); TimeStamp = 0; Key = 0; do { Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop); if (Key != 0) { for (Index = 0; mTokenList[Index] != NULL; Index++) { if (AsciiStriCmp (mTokenList[Index], Token) == 0) { Delta = CountUp?(Stop - Start):(Start - Stop); TimeStamp += Delta; Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL); AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds); break; } } } } while (Key != 0); AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL)); return EFI_SUCCESS; }
/** This service enables the sending of commands to the TPM12. @param[in] InputParameterBlockSize Size of the TPM12 input parameter block. @param[in] InputParameterBlock Pointer to the TPM12 input parameter block. @param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block. @param[in] OutputParameterBlock Pointer to the TPM12 output parameter block. @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. **/ EFI_STATUS EFIAPI Tpm12SubmitCommand ( IN UINT32 InputParameterBlockSize, IN UINT8 *InputParameterBlock, IN OUT UINT32 *OutputParameterBlockSize, IN UINT8 *OutputParameterBlock ) { EFI_STATUS Status; UINT32 TpmOutSize; TPM_RSP_COMMAND_HDR *ResponseHeader; UINT64 Current; UINT64 Previous; UINT64 Total; UINT64 Start; UINT64 End; UINT64 Timeout; INT64 Cycle; INT64 Delta; // // Make sure response buffer is big enough to hold a response header // if (*OutputParameterBlockSize < sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_BUFFER_TOO_SMALL; goto Done; } // // Get the current timer value // Current = GetPerformanceCounter(); // // Initialize local variables // Start = 0; End = 0; Total = 0; // // Retrieve the performance counter properties and compute the number of // performance counter ticks required to reach the maximum TIS timeout of // TIS_TIMEOUT_A. TIS_TIMEOUT_A is in microseconds. // Timeout = DivU64x32 ( MultU64x32 ( GetPerformanceCounterProperties (&Start, &End), TIS_TIMEOUT_A ), 1000000 ); Cycle = End - Start; if (Cycle < 0) { Cycle = -Cycle; } Cycle++; // // Send command // do { Status = WriteTpmBufferMultiple (InputParameterBlock, InputParameterBlockSize); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; if (Total >= Timeout) { Status = EFI_TIMEOUT; goto Done; } } while (EFI_ERROR (Status)); // // Receive response header // do { Status = ReadTpmBufferMultiple (OutputParameterBlock, sizeof (TPM_RSP_COMMAND_HDR)); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; if (Total >= Timeout) { Status = EFI_TIMEOUT; goto Done; } } while (EFI_ERROR (Status)); // // Check the response data header (tag, parasize and returncode) // ResponseHeader = (TPM_RSP_COMMAND_HDR *)OutputParameterBlock; if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) { Status = EFI_DEVICE_ERROR; goto Done; } TpmOutSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize)); if (TpmOutSize == sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_SUCCESS; goto Done; } if (TpmOutSize < sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_DEVICE_ERROR; goto Done; } if (*OutputParameterBlockSize < TpmOutSize) { Status = EFI_BUFFER_TOO_SMALL; goto Done; } *OutputParameterBlockSize = TpmOutSize; // // Receive the remaining data in the response header // do { Status = ReadTpmBufferMultiple ( OutputParameterBlock + sizeof (TPM_RSP_COMMAND_HDR), TpmOutSize - sizeof (TPM_RSP_COMMAND_HDR) ); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; if (Total >= Timeout) { Status = EFI_TIMEOUT; goto Done; } } while (EFI_ERROR (Status)); Done: DEBUG (( EFI_D_VERBOSE, "Tpm12SubmitCommand() Status = %r Time = %ld ms\n", Status, DivU64x64Remainder ( MultU64x32 (Total, 1000), GetPerformanceCounterProperties (NULL, NULL), NULL ) )); return Status; }
/** Create PRP lists for data transfer which is larger than 2 memory pages. Note here we calcuate the number of required PRP lists and allocate them at one time. @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance. @param[in] PhysicalAddr The physical base address of data buffer. @param[in] Pages The number of pages to be transfered. @param[out] PrpListHost The host base address of PRP lists. @param[in,out] PrpListNo The number of PRP List. @param[out] Mapping The mapping value returned from PciIo.Map(). @retval The pointer to the first PRP List of the PRP lists. **/ VOID* NvmeCreatePrpList ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_PHYSICAL_ADDRESS PhysicalAddr, IN UINTN Pages, OUT VOID **PrpListHost, IN OUT UINTN *PrpListNo, OUT VOID **Mapping ) { UINTN PrpEntryNo; UINT64 PrpListBase; UINTN PrpListIndex; UINTN PrpEntryIndex; UINT64 Remainder; EFI_PHYSICAL_ADDRESS PrpListPhyAddr; UINTN Bytes; EFI_STATUS Status; // // The number of Prp Entry in a memory page. // PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64); // // Calculate total PrpList number. // *PrpListNo = (UINTN)DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo - 1, &Remainder); if (*PrpListNo == 0) { *PrpListNo = 1; } else if ((Remainder != 0) && (Remainder != 1)) { *PrpListNo += 1; } else if (Remainder == 1) { Remainder = PrpEntryNo; } else if (Remainder == 0) { Remainder = PrpEntryNo - 1; } Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, *PrpListNo, PrpListHost, 0 ); if (EFI_ERROR (Status)) { return NULL; } Bytes = EFI_PAGES_TO_SIZE (*PrpListNo); Status = PciIo->Map ( PciIo, EfiPciIoOperationBusMasterCommonBuffer, *PrpListHost, &Bytes, &PrpListPhyAddr, Mapping ); if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (*PrpListNo))) { DEBUG ((EFI_D_ERROR, "NvmeCreatePrpList: create PrpList failure!\n")); goto EXIT; } // // Fill all PRP lists except of last one. // ZeroMem (*PrpListHost, Bytes); for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) { PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) { if (PrpEntryIndex != PrpEntryNo - 1) { // // Fill all PRP entries except of last one. // *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr; PhysicalAddr += EFI_PAGE_SIZE; } else { // // Fill last PRP entries with next PRP List pointer. // *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE; } } } // // Fill last PRP list. // PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < Remainder; ++PrpEntryIndex) { *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr; PhysicalAddr += EFI_PAGE_SIZE; } return (VOID*)(UINTN)PrpListPhyAddr; EXIT: PciIo->FreeBuffer (PciIo, *PrpListNo, *PrpListHost); return NULL; }