mirror of https://github.com/acidanthera/audk.git
SourceLevelDebugPkg: Use CPU Local APIC timer to handle timeout.
Use CPU Local APIC timer to handle timeout when read data from debug port, instead of the TimerLib in Debug Communication lib instances. It could remove much duplicated code in Debug Communication Lib instances. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17089 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
206f412113
commit
08021523f8
|
@ -380,10 +380,92 @@ UpdateMailboxContent (
|
|||
- CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
|
||||
Mailbox->HostSequenceNo = (UINT8) Value;
|
||||
break;
|
||||
case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY:
|
||||
Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT32))
|
||||
- CalculateSum8 ((UINT8 *)&Value, sizeof(UINT32));
|
||||
Mailbox->DebugTimerFrequency = (UINT32) Value;
|
||||
break;
|
||||
}
|
||||
UpdateMailboxChecksum (Mailbox);
|
||||
ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);
|
||||
}
|
||||
|
||||
/**
|
||||
Read data from debug device and save the data 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
|
||||
DebugAgentReadBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes,
|
||||
IN UINTN Timeout
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINT32 Begin;
|
||||
UINT32 TimeoutTicker;
|
||||
UINT32 TimerRound;
|
||||
UINT32 TimerFrequency;
|
||||
UINT32 TimerCycle;
|
||||
|
||||
Begin = 0;
|
||||
TimeoutTicker = 0;
|
||||
TimerRound = 0;
|
||||
TimerFrequency = GetMailboxPointer()->DebugTimerFrequency;
|
||||
TimerCycle = GetApicTimerInitCount ();
|
||||
|
||||
if (Timeout != 0) {
|
||||
Begin = GetApicTimerCurrentCount ();
|
||||
TimeoutTicker = (UINT32) DivU64x32 (
|
||||
MultU64x64 (
|
||||
TimerFrequency,
|
||||
Timeout
|
||||
),
|
||||
1000000u
|
||||
);
|
||||
TimerRound = (UINT32) DivU64x32Remainder (TimeoutTicker, TimerCycle / 2, &TimeoutTicker);
|
||||
}
|
||||
Index = 0;
|
||||
while (Index < NumberOfBytes) {
|
||||
if (DebugPortPollBuffer (Handle)) {
|
||||
DebugPortReadBuffer (Handle, Buffer + Index, 1, 0);
|
||||
Index ++;
|
||||
continue;
|
||||
}
|
||||
if (Timeout != 0) {
|
||||
if (TimerRound == 0) {
|
||||
if (IsDebugTimerTimeout (TimerCycle, Begin, TimeoutTicker)) {
|
||||
//
|
||||
// If time out occurs.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (IsDebugTimerTimeout (TimerCycle, Begin, TimerCycle / 2)) {
|
||||
TimerRound --;
|
||||
Begin = GetApicTimerCurrentCount ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Index;
|
||||
}
|
||||
|
||||
/**
|
||||
Set debug flag in mailbox.
|
||||
|
||||
|
@ -589,7 +671,7 @@ ReadRemainingBreakPacket (
|
|||
//
|
||||
// Has received start symbol, try to read the rest part
|
||||
//
|
||||
if (DebugPortReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) {
|
||||
if (DebugAgentReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) {
|
||||
//
|
||||
// Timeout occur, exit
|
||||
//
|
||||
|
@ -1046,9 +1128,9 @@ ReceivePacket (
|
|||
//
|
||||
// Find the valid start symbol
|
||||
//
|
||||
Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
|
||||
Received = DebugAgentReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
|
||||
if (Received < sizeof (DebugHeader->StartSymbol)) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugAgentReadBuffer(StartSymbol) timeout\n");
|
||||
return RETURN_TIMEOUT;
|
||||
}
|
||||
|
||||
|
@ -1060,14 +1142,14 @@ ReceivePacket (
|
|||
//
|
||||
// Read Package header till field Length
|
||||
//
|
||||
Received = DebugPortReadBuffer (
|
||||
Received = DebugAgentReadBuffer (
|
||||
Handle,
|
||||
(UINT8 *) DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command),
|
||||
OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),
|
||||
Timeout
|
||||
);
|
||||
if (Received == 0) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(Command) timeout\n");
|
||||
return RETURN_TIMEOUT;
|
||||
}
|
||||
if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {
|
||||
|
@ -1086,9 +1168,9 @@ ReceivePacket (
|
|||
//
|
||||
// Read the payload data include the CRC field
|
||||
//
|
||||
Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
|
||||
Received = DebugAgentReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
|
||||
if (Received == 0) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(SequenceNo) timeout\n");
|
||||
return RETURN_TIMEOUT;
|
||||
}
|
||||
//
|
||||
|
@ -1681,7 +1763,7 @@ SendBreakPacketToHost (
|
|||
// Poll Attach symbols from HOST and ack OK
|
||||
//
|
||||
do {
|
||||
DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
|
||||
DebugAgentReadBuffer (Handle, &InputCharacter, 1, 0);
|
||||
} while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);
|
||||
SendAckPacket (DEBUG_COMMAND_OK);
|
||||
|
||||
|
@ -2408,7 +2490,7 @@ InterruptProcess (
|
|||
//
|
||||
CurrentDebugTimerInitCount = GetApicTimerInitCount ();
|
||||
if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
|
||||
InitializeDebugTimer ();
|
||||
InitializeDebugTimer (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
// Timeout value for reading packet (unit is microsecond)
|
||||
//
|
||||
#define READ_PACKET_TIMEOUT (500 * 1000)
|
||||
#define DEBUG_TIMER_INTERVAL (100 * 1000)
|
||||
|
||||
#define SOFT_INTERRUPT_SIGNATURE SIGNATURE_32('S','O','F','T')
|
||||
#define SYSTEM_RESET_SIGNATURE SIGNATURE_32('S','Y','S','R')
|
||||
|
@ -102,6 +103,7 @@ typedef struct {
|
|||
#define DEBUG_MAILBOX_LAST_ACK 4
|
||||
#define DEBUG_MAILBOX_SEQUENCE_NO_INDEX 5
|
||||
#define DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX 6
|
||||
#define DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY 7
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union {
|
||||
|
@ -137,6 +139,7 @@ typedef struct {
|
|||
UINT8 LastAck; // The last ack packet type
|
||||
UINT8 SequenceNo;
|
||||
UINT8 HostSequenceNo;
|
||||
UINT32 DebugTimerFrequency;
|
||||
UINT8 CheckSum; // Mailbox checksum
|
||||
UINT8 ToBeCheckSum; // To be Mailbox checksum at the next
|
||||
} DEBUG_AGENT_MAILBOX;
|
||||
|
@ -469,5 +472,30 @@ ReadRemainingBreakPacket (
|
|||
IN OUT DEBUG_PACKET_HEADER *DebugHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Read data from debug channel and save the data 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
|
||||
DebugAgentReadBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle,
|
||||
IN OUT UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes,
|
||||
IN UINTN Timeout
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Code for debug timer to support debug agent library implementation.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -17,31 +17,42 @@
|
|||
/**
|
||||
Initialize CPU local APIC timer.
|
||||
|
||||
@param[out] Local APIC timer frequency returned.
|
||||
|
||||
@return 32-bit Local APIC timer init count.
|
||||
**/
|
||||
UINT32
|
||||
InitializeDebugTimer (
|
||||
VOID
|
||||
OUT UINT32 *TimerFrequency
|
||||
)
|
||||
{
|
||||
UINTN ApicTimerDivisor;
|
||||
UINT32 InitialCount;
|
||||
UINT32 ApicTimerFrequency;
|
||||
|
||||
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 (
|
||||
PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor,
|
||||
100
|
||||
ApicTimerFrequency,
|
||||
DEBUG_TIMER_INTERVAL
|
||||
),
|
||||
1000
|
||||
1000000u
|
||||
);
|
||||
|
||||
InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -87,3 +98,41 @@ SaveAndSetDebugTimerInterrupt (
|
|||
return OldDebugTimerInterruptState;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the timer is time out.
|
||||
|
||||
@param[in] TimerCycle Timer total count.
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsDebugTimerTimeout (
|
||||
IN UINT32 TimerCycle,
|
||||
IN UINT32 Timer,
|
||||
IN UINT32 TimeoutTicker
|
||||
)
|
||||
{
|
||||
UINT64 CurrentTimer;
|
||||
UINT64 Delta;
|
||||
|
||||
CurrentTimer = GetApicTimerCurrentCount ();
|
||||
|
||||
//
|
||||
// This timer counter counts down. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer < Timer) {
|
||||
Delta = Timer - CurrentTimer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = TimerCycle - (CurrentTimer - Timer);
|
||||
}
|
||||
|
||||
return (BOOLEAN) (Delta >= TimeoutTicker);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Header file for debug timer to support debug agent library implementation.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -18,11 +18,31 @@
|
|||
/**
|
||||
Initialize CPU local APIC timer.
|
||||
|
||||
@param[out] Local APIC timer frequency returned.
|
||||
|
||||
@return 32-bit Local APIC timer init count.
|
||||
**/
|
||||
UINT32
|
||||
InitializeDebugTimer (
|
||||
VOID
|
||||
OUT UINT32 *TimerFrequency
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the timer is time out.
|
||||
|
||||
@param[in] TimerCycle Timer total count.
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsDebugTimerTimeout (
|
||||
IN UINT32 TimerCycle,
|
||||
IN UINT32 Timer,
|
||||
IN UINT32 TimeoutTicker
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Debug Agent library implementition for Dxe Core and Dxr modules.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -355,6 +355,7 @@ InitializeDebugAgent (
|
|||
IA32_DESCRIPTOR IdtDescriptor;
|
||||
IA32_DESCRIPTOR *Ia32Idtr;
|
||||
IA32_IDT_ENTRY *Ia32IdtEntry;
|
||||
UINT32 DebugTimerFrequency;
|
||||
|
||||
if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
|
||||
//
|
||||
|
@ -398,10 +399,6 @@ InitializeDebugAgent (
|
|||
mSaveIdtTableSize = IdtDescriptor.Limit + 1;
|
||||
mSavedIdtTable = AllocateCopyPool (mSaveIdtTableSize, (VOID *) IdtDescriptor.Base);
|
||||
//
|
||||
// Initialize Debug Timer hardware and save its initial count
|
||||
//
|
||||
mDebugMpContext.DebugTimerInitCount = InitializeDebugTimer ();
|
||||
//
|
||||
// Check if Debug Agent initialized in DXE phase
|
||||
//
|
||||
Mailbox = GetMailboxFromConfigurationTable ();
|
||||
|
@ -417,6 +414,11 @@ InitializeDebugAgent (
|
|||
//
|
||||
SetupDebugAgentEnviroment (Mailbox);
|
||||
//
|
||||
// Initialize Debug Timer hardware and save its initial count and frequency
|
||||
//
|
||||
mDebugMpContext.DebugTimerInitCount = InitializeDebugTimer (&DebugTimerFrequency);
|
||||
UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
|
||||
//
|
||||
// For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol
|
||||
// For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()
|
||||
//
|
||||
|
@ -496,10 +498,6 @@ InitializeDebugAgent (
|
|||
mDxeCoreFlag = TRUE;
|
||||
mMultiProcessorDebugSupport = TRUE;
|
||||
//
|
||||
// Initialize Debug Timer hardware and its initial count
|
||||
//
|
||||
mDebugMpContext.DebugTimerInitCount = InitializeDebugTimer ();
|
||||
//
|
||||
// Try to get mailbox from GUIDed HOB build in PEI
|
||||
//
|
||||
HobList = Context;
|
||||
|
@ -509,6 +507,11 @@ InitializeDebugAgent (
|
|||
//
|
||||
SetupDebugAgentEnviroment (Mailbox);
|
||||
//
|
||||
// Initialize Debug Timer hardware and save its initial count and frequency
|
||||
//
|
||||
mDebugMpContext.DebugTimerInitCount = InitializeDebugTimer (&DebugTimerFrequency);
|
||||
UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
|
||||
//
|
||||
// Enable interrupt to receive Debug Timer interrupt
|
||||
//
|
||||
EnableInterrupts ();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Install Serial IO Protocol that layers on top of a Debug Communication Library instance.
|
||||
|
||||
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -676,7 +676,7 @@ SerialRead (
|
|||
if (!DebugPortPollBuffer (Handle)) {
|
||||
break;
|
||||
}
|
||||
DebugPortReadBuffer (Handle, Data8, 1, 0);
|
||||
DebugAgentReadBuffer (Handle, Data8, 1, 0);
|
||||
|
||||
if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
|
||||
//
|
||||
|
@ -752,7 +752,7 @@ DebugReadBreakFromDebugPort (
|
|||
//
|
||||
// Try to read the start symbol
|
||||
//
|
||||
DebugPortReadBuffer (Handle, Data8, 1, 0);
|
||||
DebugAgentReadBuffer (Handle, Data8, 1, 0);
|
||||
if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *Data8);
|
||||
*BreakSymbol = *Data8;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
SEC Core Debug Agent Library instance implementition.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -93,7 +93,7 @@ DebugReadBreakSymbol (
|
|||
//
|
||||
// Try to read the start symbol
|
||||
//
|
||||
DebugPortReadBuffer (Handle, Data8, 1, 0);
|
||||
DebugAgentReadBuffer (Handle, Data8, 1, 0);
|
||||
if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
|
||||
*BreakSymbol = *Data8;
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *BreakSymbol);
|
||||
|
@ -375,6 +375,7 @@ InitializeDebugAgent (
|
|||
UINT64 MailboxLocation;
|
||||
UINT64 *MailboxLocationPointer;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
UINT32 DebugTimerFrequency;
|
||||
|
||||
DisableInterrupts ();
|
||||
|
||||
|
@ -399,8 +400,11 @@ InitializeDebugAgent (
|
|||
// Save init arch type when debug agent initialized
|
||||
//
|
||||
SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL);
|
||||
|
||||
InitializeDebugTimer ();
|
||||
//
|
||||
// Initialize Debug Timer hardware and save its frequency
|
||||
//
|
||||
InitializeDebugTimer (&DebugTimerFrequency);
|
||||
UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
|
||||
|
||||
Phase2Context.InitFlag = InitFlag;
|
||||
Phase2Context.Context = Context;
|
||||
|
@ -524,8 +528,11 @@ InitializeDebugAgent (
|
|||
&MailboxLocation,
|
||||
sizeof (UINT64)
|
||||
);
|
||||
|
||||
InitializeDebugTimer ();
|
||||
//
|
||||
// Initialize Debug Timer hardware and save its frequency
|
||||
//
|
||||
InitializeDebugTimer (&DebugTimerFrequency);
|
||||
UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
|
||||
//
|
||||
// Update IDT entry to save the location pointer saved mailbox pointer
|
||||
//
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Debug Agent library implementition.
|
||||
|
||||
Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -189,6 +189,7 @@ InitializeDebugAgent (
|
|||
UINT16 IdtEntryCount;
|
||||
DEBUG_AGENT_MAILBOX *Mailbox;
|
||||
UINT64 *MailboxLocation;
|
||||
UINT32 DebugTimerFrequency;
|
||||
|
||||
switch (InitFlag) {
|
||||
case DEBUG_AGENT_INIT_SMM:
|
||||
|
@ -236,6 +237,12 @@ InitializeDebugAgent (
|
|||
// Initialized Debug Agent
|
||||
//
|
||||
InitializeDebugIdt ();
|
||||
//
|
||||
// Initialize Debug Timer hardware and save its frequency
|
||||
//
|
||||
InitializeDebugTimer (&DebugTimerFrequency);
|
||||
UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
|
||||
|
||||
DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, NULL);
|
||||
UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
|
||||
mMailboxPointer = Mailbox;
|
||||
|
@ -329,9 +336,10 @@ InitializeDebugAgent (
|
|||
|
||||
InitializeDebugIdt ();
|
||||
//
|
||||
// Initialize Debug Timer hardware and enable interrupt.
|
||||
// Initialize Debug Timer hardware and save its frequency
|
||||
//
|
||||
InitializeDebugTimer ();
|
||||
InitializeDebugTimer (&DebugTimerFrequency);
|
||||
UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
|
||||
EnableInterrupts ();
|
||||
|
||||
FindAndReportModuleImageInfo (SIZE_4KB);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Debug Port Library implementation based on serial port.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -16,82 +16,7 @@
|
|||
|
||||
#include <Library/DebugCommunicationLib.h>
|
||||
#include <Library/SerialPortLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
|
||||
#pragma pack(1)
|
||||
//
|
||||
// The internal data structure of DEBUG_PORT_HANDLE, which stores some
|
||||
// important datum which are used across various phases.
|
||||
//
|
||||
typedef struct _SERIAL_DEBUG_PORT_HANDLE{
|
||||
//
|
||||
// Timter settings
|
||||
//
|
||||
UINT64 TimerFrequency;
|
||||
UINT64 TimerCycle;
|
||||
BOOLEAN TimerCountDown;
|
||||
} SERIAL_DEBUG_PORT_HANDLE;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// The global variable which can be used after memory is ready.
|
||||
//
|
||||
SERIAL_DEBUG_PORT_HANDLE mSerialDebugPortHandle;
|
||||
|
||||
/**
|
||||
Check if the timer is timeout.
|
||||
|
||||
@param[in] SerialDebugPortHandle Pointer to Serial Debug port handle
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTimerTimeout (
|
||||
IN SERIAL_DEBUG_PORT_HANDLE *SerialDebugPortHandle,
|
||||
IN UINT64 Timer,
|
||||
IN UINT64 TimeoutTicker
|
||||
)
|
||||
{
|
||||
UINT64 CurrentTimer;
|
||||
UINT64 Delta;
|
||||
|
||||
CurrentTimer = GetPerformanceCounter ();
|
||||
|
||||
if (SerialDebugPortHandle->TimerCountDown) {
|
||||
//
|
||||
// The timer counter counts down. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer < Timer) {
|
||||
Delta = Timer - CurrentTimer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = SerialDebugPortHandle->TimerCycle - (CurrentTimer - Timer);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// The timer counter counts up. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer > Timer) {
|
||||
Delta = CurrentTimer - Timer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = SerialDebugPortHandle->TimerCycle - (Timer - CurrentTimer);
|
||||
}
|
||||
}
|
||||
|
||||
return (BOOLEAN) (Delta >= TimeoutTicker);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the debug port.
|
||||
|
@ -136,42 +61,7 @@ DebugPortInitialize (
|
|||
IN DEBUG_PORT_CONTINUE Function
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
SERIAL_DEBUG_PORT_HANDLE Handle;
|
||||
SERIAL_DEBUG_PORT_HANDLE *SerialDebugPortHandle;
|
||||
UINT64 TimerStartValue;
|
||||
UINT64 TimerEndValue;
|
||||
|
||||
//
|
||||
// Validate the PCD PcdDebugPortHandleBufferSize value
|
||||
//
|
||||
ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (SERIAL_DEBUG_PORT_HANDLE));
|
||||
|
||||
if (Context != NULL && Function == NULL) {
|
||||
SerialDebugPortHandle = (SERIAL_DEBUG_PORT_HANDLE *)Context;
|
||||
} else {
|
||||
ZeroMem (&Handle, sizeof (SERIAL_DEBUG_PORT_HANDLE));
|
||||
SerialDebugPortHandle = &Handle;
|
||||
}
|
||||
SerialDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (
|
||||
&TimerStartValue,
|
||||
&TimerEndValue
|
||||
);
|
||||
DEBUG ((EFI_D_INFO, "Serial Debug Port: TimerFrequency = 0x%lx\n", SerialDebugPortHandle->TimerFrequency));
|
||||
DEBUG ((EFI_D_INFO, "Serial Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue));
|
||||
DEBUG ((EFI_D_INFO, "Serial Debug Port: TimerEndValue = 0x%lx\n", TimerEndValue));
|
||||
|
||||
if (TimerEndValue < TimerStartValue) {
|
||||
SerialDebugPortHandle->TimerCountDown = TRUE;
|
||||
SerialDebugPortHandle->TimerCycle = TimerStartValue - TimerEndValue;
|
||||
} else {
|
||||
SerialDebugPortHandle->TimerCountDown = FALSE;
|
||||
SerialDebugPortHandle->TimerCycle = TimerEndValue - TimerStartValue;
|
||||
}
|
||||
|
||||
if (Function == NULL && Context != NULL) {
|
||||
return (DEBUG_PORT_HANDLE *) Context;
|
||||
}
|
||||
RETURN_STATUS Status;
|
||||
|
||||
Status = SerialPortInitialize ();
|
||||
if (RETURN_ERROR(Status)) {
|
||||
|
@ -179,12 +69,10 @@ DebugPortInitialize (
|
|||
}
|
||||
|
||||
if (Function != NULL) {
|
||||
Function (Context, SerialDebugPortHandle);
|
||||
} else {
|
||||
CopyMem(&mSerialDebugPortHandle, SerialDebugPortHandle, sizeof (SERIAL_DEBUG_PORT_HANDLE));
|
||||
Function (Context, NULL);
|
||||
}
|
||||
|
||||
return (DEBUG_PORT_HANDLE)(UINTN)&mSerialDebugPortHandle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,62 +101,11 @@ DebugPortReadBuffer (
|
|||
IN UINTN Timeout
|
||||
)
|
||||
{
|
||||
SERIAL_DEBUG_PORT_HANDLE *SerialDebugPortHandle;
|
||||
UINTN Index;
|
||||
UINT64 Begin;
|
||||
UINT64 TimeoutTicker;
|
||||
UINT64 TimerRound;
|
||||
|
||||
//
|
||||
// If Handle is NULL, it means memory is ready for use.
|
||||
// Use global variable to store handle value.
|
||||
//
|
||||
if (Handle == NULL) {
|
||||
SerialDebugPortHandle = &mSerialDebugPortHandle;
|
||||
} else {
|
||||
SerialDebugPortHandle = (SERIAL_DEBUG_PORT_HANDLE *)Handle;
|
||||
if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Begin = 0;
|
||||
TimeoutTicker = 0;
|
||||
TimerRound = 0;
|
||||
if (Timeout != 0) {
|
||||
Begin = GetPerformanceCounter ();
|
||||
TimeoutTicker = DivU64x32 (
|
||||
MultU64x64 (
|
||||
SerialDebugPortHandle->TimerFrequency,
|
||||
Timeout
|
||||
),
|
||||
1000000u
|
||||
);
|
||||
TimerRound = DivU64x64Remainder (
|
||||
TimeoutTicker,
|
||||
DivU64x32 (SerialDebugPortHandle->TimerCycle, 2),
|
||||
&TimeoutTicker
|
||||
);
|
||||
}
|
||||
Index = 0;
|
||||
while (Index < NumberOfBytes) {
|
||||
if (SerialPortPoll () || Timeout == 0) {
|
||||
SerialPortRead (Buffer + Index, 1);
|
||||
Index ++;
|
||||
continue;
|
||||
}
|
||||
if (TimerRound == 0) {
|
||||
if (IsTimerTimeout (SerialDebugPortHandle, Begin, TimeoutTicker)) {
|
||||
//
|
||||
// If time out occurs.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (IsTimerTimeout (SerialDebugPortHandle, Begin, DivU64x32 (SerialDebugPortHandle->TimerCycle, 2))) {
|
||||
TimerRound --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Index;
|
||||
return SerialPortRead (Buffer, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,13 +35,4 @@
|
|||
|
||||
[LibraryClasses]
|
||||
SerialPortLib
|
||||
TimerLib
|
||||
DebugLib
|
||||
BaseMemoryLib
|
||||
BaseLib
|
||||
|
||||
[PCD]
|
||||
# The value of data buffer size used for Serial debug port handle.
|
||||
# It should be equal to sizeof (SERIAL_DEBUG_PORT_HANDLE).
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|17 ## SOMETIMES_CONSUMES
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Debug Port Library implementation based on usb debug port.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -147,12 +147,6 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
|
|||
// The data buffer. Maximum length is 8 bytes.
|
||||
//
|
||||
UINT8 Data[8];
|
||||
//
|
||||
// Timter settings
|
||||
//
|
||||
UINT64 TimerFrequency;
|
||||
UINT64 TimerCycle;
|
||||
BOOLEAN TimerCountDown;
|
||||
} USB_DEBUG_PORT_HANDLE;
|
||||
#pragma pack()
|
||||
|
||||
|
@ -161,58 +155,6 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
|
|||
//
|
||||
USB_DEBUG_PORT_HANDLE mDebugCommunicationLibUsbDebugPortHandle;
|
||||
|
||||
/**
|
||||
Check if the timer is timeout.
|
||||
|
||||
@param[in] UsbDebugPortHandle Pointer to USB Debug port handle
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTimerTimeout (
|
||||
IN USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle,
|
||||
IN UINT64 Timer,
|
||||
IN UINT64 TimeoutTicker
|
||||
)
|
||||
{
|
||||
UINT64 CurrentTimer;
|
||||
UINT64 Delta;
|
||||
|
||||
CurrentTimer = GetPerformanceCounter ();
|
||||
|
||||
if (UsbDebugPortHandle->TimerCountDown) {
|
||||
//
|
||||
// The timer counter counts down. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer < Timer) {
|
||||
Delta = Timer - CurrentTimer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = UsbDebugPortHandle->TimerCycle - (CurrentTimer - Timer);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// The timer counter counts up. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer > Timer) {
|
||||
Delta = CurrentTimer - Timer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = UsbDebugPortHandle->TimerCycle - (Timer - CurrentTimer);
|
||||
}
|
||||
}
|
||||
|
||||
return (BOOLEAN) (Delta >= TimeoutTicker);
|
||||
}
|
||||
|
||||
/**
|
||||
Calculate the usb debug port bar address.
|
||||
|
||||
|
@ -834,23 +776,12 @@ DebugPortReadBuffer (
|
|||
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) {
|
||||
if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
|
||||
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.
|
||||
|
@ -871,117 +802,21 @@ DebugPortReadBuffer (
|
|||
UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);
|
||||
|
||||
//
|
||||
// First read data from buffer, then read debug port hw to get received data.
|
||||
// Read data from buffer
|
||||
//
|
||||
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) {
|
||||
if (UsbDebugPortHandle->DataCount < 1) {
|
||||
return 0;
|
||||
} else {
|
||||
*Buffer = UsbDebugPortHandle->Data[0];
|
||||
for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
|
||||
if ((Index + 1) >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Total + Index];
|
||||
UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Index + 1];
|
||||
}
|
||||
UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total);
|
||||
UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1208,8 +1043,6 @@ DebugPortInitialize (
|
|||
RETURN_STATUS Status;
|
||||
USB_DEBUG_PORT_HANDLE Handle;
|
||||
USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
|
||||
UINT64 TimerStartValue;
|
||||
UINT64 TimerEndValue;
|
||||
|
||||
//
|
||||
// Validate the PCD PcdDebugPortHandleBufferSize value
|
||||
|
@ -1223,22 +1056,6 @@ DebugPortInitialize (
|
|||
UsbDebugPortHandle = &Handle;
|
||||
}
|
||||
|
||||
UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (
|
||||
&TimerStartValue,
|
||||
&TimerEndValue
|
||||
);
|
||||
DEBUG ((EFI_D_INFO, "USB Debug Port: TimerFrequency = 0x%lx\n", UsbDebugPortHandle->TimerFrequency));
|
||||
DEBUG ((EFI_D_INFO, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue));
|
||||
DEBUG ((EFI_D_INFO, "USB Debug Port: TimerEndValue = 0x%lx\n", TimerEndValue));
|
||||
|
||||
if (TimerEndValue < TimerStartValue) {
|
||||
UsbDebugPortHandle->TimerCountDown = TRUE;
|
||||
UsbDebugPortHandle->TimerCycle = TimerStartValue - TimerEndValue;
|
||||
} else {
|
||||
UsbDebugPortHandle->TimerCountDown = FALSE;
|
||||
UsbDebugPortHandle->TimerCycle = TimerEndValue - TimerStartValue;
|
||||
}
|
||||
|
||||
if (Function == NULL && Context != NULL) {
|
||||
return (DEBUG_PORT_HANDLE *) Context;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbEhciPciAddress ## CONSUMES
|
||||
# The value of data buffer size used for USB debug port handle.
|
||||
# It should be equal to sizeof (USB_DEBUG_PORT_HANDLE).
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|40 ## SOMETIMES_CONSUMES
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|23 ## SOMETIMES_CONSUMES
|
||||
|
||||
[LibraryClasses]
|
||||
TimerLib
|
||||
|
|
|
@ -186,58 +186,6 @@ ProgramXhciBaseAddress (
|
|||
return XhciMmioBase;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the timer is timeout.
|
||||
|
||||
@param[in] UsbDebugPortHandle Pointer to USB Debug port handle
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTimerTimeout (
|
||||
IN USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle,
|
||||
IN UINT64 Timer,
|
||||
IN UINT64 TimeoutTicker
|
||||
)
|
||||
{
|
||||
UINT64 CurrentTimer;
|
||||
UINT64 Delta;
|
||||
|
||||
CurrentTimer = GetPerformanceCounter ();
|
||||
|
||||
if (UsbDebugPortHandle->TimerCountDown) {
|
||||
//
|
||||
// The timer counter counts down. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer < Timer) {
|
||||
Delta = Timer - CurrentTimer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = UsbDebugPortHandle->TimerCycle - (CurrentTimer - Timer);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// The timer counter counts up. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer > Timer) {
|
||||
Delta = CurrentTimer - Timer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = UsbDebugPortHandle->TimerCycle - (Timer - CurrentTimer);
|
||||
}
|
||||
}
|
||||
|
||||
return (BOOLEAN) (Delta >= TimeoutTicker);
|
||||
}
|
||||
|
||||
/**
|
||||
Update XHC MMIO base address when MMIO base address is changed.
|
||||
|
||||
|
@ -825,25 +773,13 @@ DebugPortReadBuffer (
|
|||
{
|
||||
USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
|
||||
RETURN_STATUS Status;
|
||||
UINTN Received;
|
||||
UINTN Total;
|
||||
UINTN Remaining;
|
||||
UINT8 Index;
|
||||
UINTN Length;
|
||||
UINT64 Begin;
|
||||
UINT64 TimeoutTicker;
|
||||
UINT64 TimerRound;
|
||||
EFI_PHYSICAL_ADDRESS XhciMmioBase;
|
||||
UINT8 *Data;
|
||||
|
||||
if (NumberOfBytes == 0 || Buffer == NULL) {
|
||||
if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
|
||||
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.
|
||||
|
@ -858,9 +794,6 @@ DebugPortReadBuffer (
|
|||
return 0;
|
||||
}
|
||||
|
||||
XhciMmioBase = ProgramXhciBaseAddress ();
|
||||
UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);
|
||||
|
||||
if (NeedReinitializeHardware(UsbDebugPortHandle)) {
|
||||
Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
|
||||
if (RETURN_ERROR(Status)) {
|
||||
|
@ -871,114 +804,22 @@ DebugPortReadBuffer (
|
|||
Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;
|
||||
|
||||
//
|
||||
// First read data from buffer, then read debug port hw to get received data.
|
||||
// Read data from buffer
|
||||
//
|
||||
if (UsbDebugPortHandle->DataCount > 0) {
|
||||
if (NumberOfBytes <= UsbDebugPortHandle->DataCount) {
|
||||
Total = NumberOfBytes;
|
||||
} else {
|
||||
Total = UsbDebugPortHandle->DataCount;
|
||||
}
|
||||
if (UsbDebugPortHandle->DataCount < 1) {
|
||||
return 0;
|
||||
} else {
|
||||
*Buffer = Data[0];
|
||||
|
||||
for (Index = 0; Index < Total; Index++) {
|
||||
Buffer[Index] = Data[Index];
|
||||
}
|
||||
|
||||
for (Index = 0; Index < UsbDebugPortHandle->DataCount - Total; Index++) {
|
||||
if (Total + Index >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
|
||||
for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
|
||||
if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
Data[Index] = Data[Total + Index];
|
||||
Data[Index] = Data[Index + 1];
|
||||
}
|
||||
UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total);
|
||||
UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// If Timeout is equal to 0, then it means it should always wait until all data 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 >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
|
||||
Received = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
|
||||
Status = XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, Buffer + Total, &Received, DATA_TRANSFER_READ_TIMEOUT);
|
||||
} else {
|
||||
Received = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
|
||||
Status = XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, (VOID *)Data, &Received, DATA_TRANSFER_READ_TIMEOUT);
|
||||
UsbDebugPortHandle->DataCount = (UINT8) Received;
|
||||
|
||||
if (Remaining <= Received) {
|
||||
//
|
||||
// The data received are more than required
|
||||
//
|
||||
Length = (UINT8)Remaining;
|
||||
} else {
|
||||
//
|
||||
// The data received are less than the remaining bytes
|
||||
//
|
||||
Length = (UINT8)Received;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy required data from the data buffer to user buffer.
|
||||
//
|
||||
for (Index = 0; Index < Length; Index++) {
|
||||
(Buffer + Total)[Index] = 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 >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
Data[Index] = Data[Length + Index];
|
||||
}
|
||||
//
|
||||
// fixup the real required length of data.
|
||||
//
|
||||
Received = Length;
|
||||
}
|
||||
Total += Received;
|
||||
}
|
||||
return Total;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1179,8 +1020,6 @@ DebugPortInitialize (
|
|||
RETURN_STATUS Status;
|
||||
USB3_DEBUG_PORT_HANDLE Handle;
|
||||
USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
|
||||
UINT64 TimerStartValue;
|
||||
UINT64 TimerEndValue;
|
||||
|
||||
//
|
||||
// Validate the PCD PcdDebugPortHandleBufferSize value
|
||||
|
@ -1194,19 +1033,6 @@ DebugPortInitialize (
|
|||
UsbDebugPortHandle = &Handle;
|
||||
}
|
||||
|
||||
UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (
|
||||
&TimerStartValue,
|
||||
&TimerEndValue
|
||||
);
|
||||
|
||||
if (TimerEndValue < TimerStartValue) {
|
||||
UsbDebugPortHandle->TimerCountDown = TRUE;
|
||||
UsbDebugPortHandle->TimerCycle = TimerStartValue - TimerEndValue;
|
||||
} else {
|
||||
UsbDebugPortHandle->TimerCountDown = FALSE;
|
||||
UsbDebugPortHandle->TimerCycle = TimerEndValue - TimerStartValue;
|
||||
}
|
||||
|
||||
if (Function == NULL && Context != NULL) {
|
||||
return (DEBUG_PORT_HANDLE *) Context;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
# The value of data buffer size used for USB debug port handle.
|
||||
# It should be equal to sizeof (USB3_DEBUG_PORT_HANDLE).
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|256 ## SOMETIMES_CONSUMES
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|239 ## SOMETIMES_CONSUMES
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
#define DATA_TRANSFER_WRITE_TIMEOUT 0
|
||||
#define DATA_TRANSFER_READ_TIMEOUT 50000
|
||||
#define DATA_TRANSFER_POLL_TIMEOUT 1000
|
||||
|
||||
#define XHC_DEBUG_PORT_1_MILLISECOND 1000
|
||||
//
|
||||
// XHCI port power off/on delay
|
||||
//
|
||||
|
@ -524,13 +524,6 @@ typedef struct _USB3_DEBUG_PORT_INSTANCE {
|
|||
// The data buffer address for data read and poll.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS Data;
|
||||
//
|
||||
// Timter settings
|
||||
//
|
||||
UINT64 TimerFrequency;
|
||||
UINT64 TimerCycle;
|
||||
BOOLEAN TimerCountDown;
|
||||
|
||||
} USB3_DEBUG_PORT_HANDLE;
|
||||
|
||||
#pragma pack()
|
||||
|
@ -735,22 +728,4 @@ XhcDataTransfer (
|
|||
IN UINTN Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the timer is timeout.
|
||||
|
||||
@param[in] UsbDebugPortHandle Pointer to USB Debug port handle
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTimerTimeout (
|
||||
IN USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle,
|
||||
IN UINT64 Timer,
|
||||
IN UINT64 TimeoutTicker
|
||||
);
|
||||
|
||||
#endif //__SERIAL_PORT_LIB_USB__
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
# The value of data buffer size used for USB debug port handle.
|
||||
# It should be equal to sizeof (USB3_DEBUG_PORT_HANDLE).
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|256 ## SOMETIMES_CONSUMES
|
||||
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|239 ## SOMETIMES_CONSUMES
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
|
|
|
@ -356,58 +356,31 @@ XhcExecTransfer (
|
|||
)
|
||||
{
|
||||
TRANSFER_RING *Ring;
|
||||
UINT64 Begin;
|
||||
UINT64 TimeoutTicker;
|
||||
UINT64 TimerRound;
|
||||
TRB_TEMPLATE *Trb;
|
||||
UINTN Loop;
|
||||
UINTN Index;
|
||||
|
||||
Begin = 0;
|
||||
TimeoutTicker = 0;
|
||||
TimerRound = 0;
|
||||
|
||||
XhcRingDoorBell (Handle, Urb);
|
||||
|
||||
if (Timeout != 0) {
|
||||
Begin = GetPerformanceCounter ();
|
||||
TimeoutTicker = DivU64x32 (
|
||||
MultU64x64 (
|
||||
Handle->TimerFrequency,
|
||||
Timeout
|
||||
),
|
||||
1000000u
|
||||
);
|
||||
TimerRound = DivU64x64Remainder (
|
||||
TimeoutTicker,
|
||||
DivU64x32 (Handle->TimerCycle, 2),
|
||||
&TimeoutTicker
|
||||
);
|
||||
Loop = Timeout / XHC_DEBUG_PORT_1_MILLISECOND;
|
||||
if (Timeout == 0) {
|
||||
Loop = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
XhcRingDoorBell (Handle, Urb);
|
||||
//
|
||||
// Event Ring Not Empty bit can only be set to 1 by XHC after ringing door bell with some delay.
|
||||
//
|
||||
while (TRUE) {
|
||||
if (Timeout != 0) {
|
||||
if (TimerRound == 0) {
|
||||
if (IsTimerTimeout (Handle, Begin, TimeoutTicker)) {
|
||||
//
|
||||
// If time out occurs.
|
||||
//
|
||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (IsTimerTimeout (Handle, Begin, DivU64x32 (Handle->TimerCycle, 2))) {
|
||||
TimerRound --;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Index = 0; Index < Loop; Index++) {
|
||||
XhcCheckUrbResult (Handle, Urb);
|
||||
if (Urb->Finished) {
|
||||
break;
|
||||
}
|
||||
MicroSecondDelay (XHC_DEBUG_PORT_1_MILLISECOND);
|
||||
}
|
||||
if (Index == Loop) {
|
||||
//
|
||||
// If time out occurs.
|
||||
//
|
||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
//
|
||||
// If URB transfer is error, restore transfer ring to original value before URB transfer
|
||||
// This will make the current transfer TRB is always at the latest unused one in transfer ring.
|
||||
|
|
Loading…
Reference in New Issue