1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698 |
- /** @file
- Common Debug Agent library implementation. It mainly includes
- the first C function called by exception/interrupt handlers,
- read/write debug packet to communication with HOST based on transfer
- protocol.
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "DebugAgent.h"
- #include "Ia32/DebugException.h"
- GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
- GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.5) ...\r\n";
- GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";
- GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";
- GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";
- //
- // Vector Handoff Info list used by Debug Agent for persist
- //
- GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = {
- {
- DEBUG_EXCEPT_DIVIDE_ERROR, // Vector 0
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_DEBUG, // Vector 1
- EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_NMI, // Vector 2
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_BREAKPOINT, // Vector 3
- EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_OVERFLOW, // Vector 4
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_BOUND, // Vector 5
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_INVALID_OPCODE, // Vector 6
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_DOUBLE_FAULT, // Vector 8
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_INVALID_TSS, // Vector 10
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_SEG_NOT_PRESENT, // Vector 11
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_STACK_FAULT, // Vector 12
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_GP_FAULT, // Vector 13
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_PAGE_FAULT, // Vector 14
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_FP_ERROR, // Vector 16
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_ALIGNMENT_CHECK, // Vector 17
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_MACHINE_CHECK, // Vector 18
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_EXCEPT_SIMD, // Vector 19
- EFI_VECTOR_HANDOFF_HOOK_BEFORE,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_TIMER_VECTOR, // Vector 32
- EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
- EFI_DEBUG_AGENT_GUID
- },
- {
- DEBUG_MAILBOX_VECTOR, // Vector 33
- EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
- EFI_DEBUG_AGENT_GUID
- },
- {
- 0,
- EFI_VECTOR_HANDOFF_LAST_ENTRY,
- { 0 }
- }
- };
- GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO);
- /**
- Calculate CRC16 for target data.
- @param[in] Data The target data.
- @param[in] DataSize The target data size.
- @param[in] Crc Initial CRC.
- @return UINT16 The CRC16 value.
- **/
- UINT16
- CalculateCrc16 (
- IN UINT8 *Data,
- IN UINTN DataSize,
- IN UINT16 Crc
- )
- {
- UINTN Index;
- UINTN BitIndex;
- for (Index = 0; Index < DataSize; Index++) {
- Crc ^= (UINT16)Data[Index];
- for (BitIndex = 0; BitIndex < 8; BitIndex++) {
- if ((Crc & 0x8000) != 0) {
- Crc <<= 1;
- Crc ^= 0x1021;
- } else {
- Crc <<= 1;
- }
- }
- }
- return Crc;
- }
- /**
- Read IDT entry to check if IDT entries are setup by Debug Agent.
- @retval TRUE IDT entries were setup by Debug Agent.
- @retval FALSE IDT entries were not setup by Debug Agent.
- **/
- BOOLEAN
- IsDebugAgentInitialzed (
- VOID
- )
- {
- UINTN InterruptHandler;
- InterruptHandler = (UINTN)GetExceptionHandlerInIdtEntry (0);
- if ((InterruptHandler >= 4) && (*(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE)) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- /**
- Find and report module image info to HOST.
- @param[in] AlignSize Image aligned size.
- **/
- VOID
- FindAndReportModuleImageInfo (
- IN UINTN AlignSize
- )
- {
- UINTN Pe32Data;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
- //
- // Find Image Base
- //
- Pe32Data = PeCoffSearchImageBase ((UINTN)mErrorMsgVersionAlert);
- if (Pe32Data != 0) {
- ImageContext.ImageAddress = Pe32Data;
- ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
- PeCoffLoaderRelocateImageExtraAction (&ImageContext);
- }
- }
- /**
- Trigger one software interrupt to debug agent to handle it.
- @param[in] Signature Software interrupt signature.
- **/
- VOID
- TriggerSoftInterrupt (
- IN UINT32 Signature
- )
- {
- UINTN Dr0;
- UINTN Dr1;
- //
- // Save Debug Register State
- //
- Dr0 = AsmReadDr0 ();
- Dr1 = AsmReadDr1 ();
- //
- // DR0 = Signature
- //
- AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);
- AsmWriteDr1 (Signature);
- //
- // Do INT3 to communicate with HOST side
- //
- CpuBreakpoint ();
- //
- // Restore Debug Register State only when Host didn't change it inside exception handler.
- // Dr registers can only be changed by setting the HW breakpoint.
- //
- AsmWriteDr0 (Dr0);
- AsmWriteDr1 (Dr1);
- }
- /**
- Calculate Mailbox checksum and update the checksum field.
- @param[in] Mailbox Debug Agent Mailbox pointer.
- **/
- VOID
- UpdateMailboxChecksum (
- IN DEBUG_AGENT_MAILBOX *Mailbox
- )
- {
- Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);
- }
- /**
- Verify Mailbox checksum.
- If checksum error, print debug message and run init dead loop.
- @param[in] Mailbox Debug Agent Mailbox pointer.
- **/
- VOID
- VerifyMailboxChecksum (
- IN DEBUG_AGENT_MAILBOX *Mailbox
- )
- {
- UINT8 CheckSum;
- CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);
- //
- // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
- // and ToBeCheckSum field to validate the mail box.
- //
- if ((CheckSum != Mailbox->CheckSum) && (CheckSum != Mailbox->ToBeCheckSum)) {
- DEBUG ((DEBUG_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
- DEBUG ((DEBUG_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum));
- CpuDeadLoop ();
- }
- }
- /**
- Update Mailbox content by index.
- @param[in] Mailbox Debug Agent Mailbox pointer.
- @param[in] Index Mailbox content index.
- @param[in] Value Value to be set into Mailbox.
- **/
- VOID
- UpdateMailboxContent (
- IN DEBUG_AGENT_MAILBOX *Mailbox,
- IN UINTN Index,
- IN UINT64 Value
- )
- {
- AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);
- switch (Index) {
- case DEBUG_MAILBOX_DEBUG_FLAG_INDEX:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugFlag.Uint64, sizeof (UINT64))
- - CalculateSum8 ((UINT8 *)&Value, sizeof (UINT64));
- Mailbox->DebugFlag.Uint64 = Value;
- break;
- case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugPortHandle, sizeof (UINTN))
- - CalculateSum8 ((UINT8 *)&Value, sizeof (UINTN));
- Mailbox->DebugPortHandle = (UINTN)Value;
- break;
- case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->ExceptionBufferPointer, sizeof (UINTN))
- - CalculateSum8 ((UINT8 *)&Value, sizeof (UINTN));
- Mailbox->ExceptionBufferPointer = (UINTN)Value;
- break;
- case DEBUG_MAILBOX_LAST_ACK:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->LastAck, sizeof (UINT8))
- - CalculateSum8 ((UINT8 *)&Value, sizeof (UINT8));
- Mailbox->LastAck = (UINT8)Value;
- break;
- case DEBUG_MAILBOX_SEQUENCE_NO_INDEX:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->SequenceNo, sizeof (UINT8))
- - CalculateSum8 ((UINT8 *)&Value, sizeof (UINT8));
- Mailbox->SequenceNo = (UINT8)Value;
- break;
- case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof (UINT8))
- - CalculateSum8 ((UINT8 *)&Value, sizeof (UINT8));
- Mailbox->HostSequenceNo = (UINT8)Value;
- break;
- case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY:
- Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugTimerFrequency, 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.
- @param[in] FlagMask Debug flag mask value.
- @param[in] FlagValue Debug flag value.
- **/
- VOID
- SetDebugFlag (
- IN UINT64 FlagMask,
- IN UINT32 FlagValue
- )
- {
- DEBUG_AGENT_MAILBOX *Mailbox;
- UINT64 Data64;
- Mailbox = GetMailboxPointer ();
- Data64 = (Mailbox->DebugFlag.Uint64 & ~FlagMask) |
- (LShiftU64 ((UINT64)FlagValue, LowBitSet64 (FlagMask)) & FlagMask);
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_FLAG_INDEX, Data64);
- }
- /**
- Get debug flag in mailbox.
- @param[in] FlagMask Debug flag mask value.
- @return Debug flag value.
- **/
- UINT32
- GetDebugFlag (
- IN UINT64 FlagMask
- )
- {
- DEBUG_AGENT_MAILBOX *Mailbox;
- UINT32 DebugFlag;
- Mailbox = GetMailboxPointer ();
- DebugFlag = (UINT32)RShiftU64 (Mailbox->DebugFlag.Uint64 & FlagMask, LowBitSet64 (FlagMask));
- return DebugFlag;
- }
- /**
- Send a debug message packet to the debug port.
- @param[in] Buffer The debug message.
- @param[in] Length The length of debug message.
- **/
- VOID
- SendDebugMsgPacket (
- IN CHAR8 *Buffer,
- IN UINTN Length
- )
- {
- DEBUG_PACKET_HEADER DebugHeader;
- DEBUG_PORT_HANDLE Handle;
- Handle = GetDebugPortHandle ();
- DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
- DebugHeader.Command = DEBUG_COMMAND_PRINT_MESSAGE;
- DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER) + (UINT8)Length;
- DebugHeader.SequenceNo = 0xEE;
- DebugHeader.Crc = 0;
- DebugHeader.Crc = CalculateCrc16 (
- (UINT8 *)Buffer,
- Length,
- CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0)
- );
- DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));
- DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length);
- }
- /**
- Prints a debug message to the debug port if the specified error level is enabled.
- If any bit in ErrorLevel is also set in Mainbox, then print the message specified
- by Format and the associated variable argument list to the debug port.
- @param[in] ErrorLevel The error level of the debug message.
- @param[in] Format Format string for the debug message to print.
- @param[in] ... Variable argument list whose contents are accessed
- based on the format string specified by Format.
- **/
- VOID
- EFIAPI
- DebugAgentMsgPrint (
- IN UINT8 ErrorLevel,
- IN CHAR8 *Format,
- ...
- )
- {
- CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];
- VA_LIST Marker;
- //
- // Check driver debug mask value and global mask
- //
- if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {
- return;
- }
- //
- // Convert the DEBUG() message to an ASCII String
- //
- VA_START (Marker, Format);
- AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
- VA_END (Marker);
- SendDebugMsgPacket (Buffer, AsciiStrLen (Buffer));
- }
- /**
- Prints a debug message to the debug output device if the specified error level is enabled.
- If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
- GetDebugPrintErrorLevel (), then print the message specified by Format and the
- associated variable argument list to the debug output device.
- If Format is NULL, then ASSERT().
- @param[in] ErrorLevel The error level of the debug message.
- @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
- @param[in] Data Variable argument list whose contents are accessed
- @param[in] Length based on the format string specified by Format.
- **/
- VOID
- EFIAPI
- DebugAgentDataMsgPrint (
- IN UINT8 ErrorLevel,
- IN BOOLEAN IsSend,
- IN UINT8 *Data,
- IN UINT8 Length
- )
- {
- CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];
- CHAR8 *DestBuffer;
- UINTN Index;
- //
- // Check driver debug mask value and global mask
- //
- if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {
- return;
- }
- DestBuffer = Buffer;
- if (IsSend) {
- DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Sent data [ ");
- } else {
- DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Received data [ ");
- }
- Index = 0;
- while (TRUE) {
- if (DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6) {
- //
- // If there was no enough space in buffer, send out the debug message,
- // reserving 6 bytes is for the last data and end characters "]\n".
- //
- SendDebugMsgPacket (Buffer, DestBuffer - Buffer);
- DestBuffer = Buffer;
- }
- DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);
- Index++;
- if (Index >= Length) {
- //
- // The last character of debug message has been formatted in buffer
- //
- DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");
- SendDebugMsgPacket (Buffer, DestBuffer - Buffer);
- break;
- }
- }
- }
- /**
- Read remaining debug packet except for the start symbol
- @param[in] Handle Pointer to Debug Port handle.
- @param[in, out] DebugHeader Debug header buffer including start symbol.
- @retval EFI_SUCCESS Read the symbol in BreakSymbol.
- @retval EFI_CRC_ERROR CRC check fail.
- @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
- @retval EFI_DEVICE_ERROR Receive the old or response packet.
- **/
- EFI_STATUS
- ReadRemainingBreakPacket (
- IN DEBUG_PORT_HANDLE Handle,
- IN OUT DEBUG_PACKET_HEADER *DebugHeader
- )
- {
- UINT16 Crc;
- DEBUG_AGENT_MAILBOX *Mailbox;
- //
- // Has received start symbol, try to read the rest part
- //
- 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
- //
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Timeout in Debug Timer interrupt\n");
- return EFI_TIMEOUT;
- }
- Crc = DebugHeader->Crc;
- DebugHeader->Crc = 0;
- if (CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0) != Crc) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Debug Timer CRC (%x) against (%x)\n", Crc, CalculateCrc16 ((UINT8 *)&DebugHeader, DebugHeader->Length, 0));
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);
- return EFI_CRC_ERROR;
- }
- Mailbox = GetMailboxPointer ();
- if (IS_REQUEST (DebugHeader)) {
- if (DebugHeader->SequenceNo == (UINT8)(Mailbox->HostSequenceNo + 1)) {
- //
- // Only update HostSequenceNo for new command packet
- //
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);
- return EFI_SUCCESS;
- }
- if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {
- return EFI_SUCCESS;
- }
- }
- return EFI_DEVICE_ERROR;
- }
- /**
- Check if HOST is attached based on Mailbox.
- @retval TRUE HOST is attached.
- @retval FALSE HOST is not attached.
- **/
- BOOLEAN
- IsHostAttached (
- VOID
- )
- {
- return (BOOLEAN)(GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);
- }
- /**
- Set HOST connect flag in Mailbox.
- @param[in] Attached Attach status.
- **/
- VOID
- SetHostAttached (
- IN BOOLEAN Attached
- )
- {
- DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);
- SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);
- }
- /**
- Set debug setting of Debug Agent in Mailbox.
- @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
- @retval RETURN_SUCCESS The setting is set successfully.
- @retval RETURN_UNSUPPORTED The Key value is not supported.
- **/
- RETURN_STATUS
- SetDebugSetting (
- IN DEBUG_DATA_SET_DEBUG_SETTING *DebugSetting
- )
- {
- RETURN_STATUS Status;
- Status = RETURN_SUCCESS;
- switch (DebugSetting->Key) {
- case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:
- SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);
- break;
- case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:
- SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value);
- break;
- case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK:
- SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value);
- break;
- default:
- Status = RETURN_UNSUPPORTED;
- }
- return Status;
- }
- /**
- Execute GO command.
- @param[in] CpuContext Pointer to saved CPU context.
- **/
- VOID
- CommandGo (
- IN DEBUG_CPU_CONTEXT *CpuContext
- )
- {
- IA32_EFLAGS32 *Eflags;
- Eflags = (IA32_EFLAGS32 *)&CpuContext->Eflags;
- Eflags->Bits.TF = 0;
- Eflags->Bits.RF = 1;
- }
- /**
- Execute Stepping command.
- @param[in] CpuContext Pointer to saved CPU context.
- **/
- VOID
- CommandStepping (
- IN DEBUG_CPU_CONTEXT *CpuContext
- )
- {
- IA32_EFLAGS32 *Eflags;
- Eflags = (IA32_EFLAGS32 *)&CpuContext->Eflags;
- Eflags->Bits.TF = 1;
- Eflags->Bits.RF = 1;
- //
- // Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping
- //
- SetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG, Eflags->Bits.IF);
- Eflags->Bits.IF = 0;
- //
- // Set Stepping Flag
- //
- SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);
- }
- /**
- Do some cleanup after Stepping command done.
- @param[in] CpuContext Pointer to saved CPU context.
- **/
- VOID
- CommandSteppingCleanup (
- IN DEBUG_CPU_CONTEXT *CpuContext
- )
- {
- IA32_EFLAGS32 *Eflags;
- Eflags = (IA32_EFLAGS32 *)&CpuContext->Eflags;
- //
- // Restore EFLAGS.IF
- //
- Eflags->Bits.IF = GetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG);
- //
- // Clear Stepping flag
- //
- SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);
- }
- /**
- Set debug register for hardware breakpoint.
- @param[in] CpuContext Pointer to saved CPU context.
- @param[in] SetHwBreakpoint Hardware breakpoint to be set.
- **/
- VOID
- SetDebugRegister (
- IN DEBUG_CPU_CONTEXT *CpuContext,
- IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint
- )
- {
- UINT8 RegisterIndex;
- UINTN Dr7Value;
- RegisterIndex = SetHwBreakpoint->Type.Index;
- //
- // Set debug address
- //
- *((UINTN *)&CpuContext->Dr0 + RegisterIndex) = (UINTN)SetHwBreakpoint->Address;
- Dr7Value = CpuContext->Dr7;
- //
- // Enable Gx, Lx
- //
- Dr7Value |= (UINTN)(0x3 << (RegisterIndex * 2));
- //
- // Set RWx and Lenx
- //
- Dr7Value &= (UINTN)(~(0xf << (16 + RegisterIndex * 4)));
- Dr7Value |= (UINTN)((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);
- //
- // Enable GE, LE
- //
- Dr7Value |= 0x300;
- CpuContext->Dr7 = Dr7Value;
- }
- /**
- Clear debug register for hardware breakpoint.
- @param[in] CpuContext Pointer to saved CPU context.
- @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
- **/
- VOID
- ClearDebugRegister (
- IN DEBUG_CPU_CONTEXT *CpuContext,
- IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint
- )
- {
- if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {
- CpuContext->Dr0 = 0;
- CpuContext->Dr7 &= (UINTN)(~(0x3 << 0));
- }
- if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {
- CpuContext->Dr1 = 0;
- CpuContext->Dr7 &= (UINTN)(~(0x3 << 2));
- }
- if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {
- CpuContext->Dr2 = 0;
- CpuContext->Dr7 &= (UINTN)(~(0x3 << 4));
- }
- if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {
- CpuContext->Dr3 = 0;
- CpuContext->Dr7 &= (UINTN)(~(0x3 << 6));
- }
- }
- /**
- Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
- @param[in] Index Register index.
- @param[out] Width Register width returned.
- @return Offset in the FPU Save State.
- **/
- UINT16
- ArchReadFxStatOffset (
- IN UINT8 Index,
- OUT UINT8 *Width
- )
- {
- if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
- switch (Index) {
- case SOFT_DEBUGGER_REGISTER_FP_FCW:
- *Width = (UINT8)sizeof (UINT16);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Fcw);
- case SOFT_DEBUGGER_REGISTER_FP_FSW:
- *Width = (UINT8)sizeof (UINT16);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Fsw);
- case SOFT_DEBUGGER_REGISTER_FP_FTW:
- *Width = (UINT8)sizeof (UINT16);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Ftw);
- case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
- *Width = (UINT8)sizeof (UINT16);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Opcode);
- case SOFT_DEBUGGER_REGISTER_FP_EIP:
- *Width = (UINT8)sizeof (UINT32);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Eip);
- case SOFT_DEBUGGER_REGISTER_FP_CS:
- *Width = (UINT8)sizeof (UINT16);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Cs);
- case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
- *Width = (UINT8)sizeof (UINT32);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, DataOffset);
- case SOFT_DEBUGGER_REGISTER_FP_DS:
- *Width = (UINT8)sizeof (UINT16);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Ds);
- case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
- *Width = (UINT8)sizeof (UINT32);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Mxcsr);
- case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
- *Width = (UINT8)sizeof (UINT32);
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask);
- }
- }
- if (Index <= SOFT_DEBUGGER_REGISTER_ST7) {
- *Width = 10;
- } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) {
- *Width = 16;
- } else {
- //
- // MMX register
- //
- *Width = 8;
- Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
- }
- return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;
- }
- /**
- Return the pointer of the register value in the CPU saved context.
- @param[in] CpuContext Pointer to saved CPU context.
- @param[in] Index Register index value.
- @param[out] Width Data width to read.
- @return The pointer in the CPU saved context.
- **/
- UINT8 *
- ArchReadRegisterBuffer (
- IN DEBUG_CPU_CONTEXT *CpuContext,
- IN UINT8 Index,
- OUT UINT8 *Width
- )
- {
- UINT8 *Buffer;
- if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
- Buffer = (UINT8 *)CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN);
- *Width = (UINT8)sizeof (UINTN);
- } else {
- //
- // FPU/MMX/XMM registers
- //
- Buffer = (UINT8 *)CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width);
- }
- return Buffer;
- }
- /**
- Send the packet without data to HOST.
- @param[in] CommandType Type of Command.
- @param[in] SequenceNo Sequence number.
- **/
- VOID
- SendPacketWithoutData (
- IN UINT8 CommandType,
- IN UINT8 SequenceNo
- )
- {
- DEBUG_PACKET_HEADER DebugHeader;
- DEBUG_PORT_HANDLE Handle;
- Handle = GetDebugPortHandle ();
- DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
- DebugHeader.Command = CommandType;
- DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);
- DebugHeader.SequenceNo = SequenceNo;
- DebugHeader.Crc = 0;
- DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *)&DebugHeader, DebugHeader.Length);
- DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, DebugHeader.Length);
- }
- /**
- Send acknowledge packet to HOST.
- @param[in] AckCommand Type of Acknowledge packet.
- **/
- VOID
- SendAckPacket (
- IN UINT8 AckCommand
- )
- {
- UINT8 SequenceNo;
- DEBUG_AGENT_MAILBOX *Mailbox;
- if (AckCommand != DEBUG_COMMAND_OK) {
- //
- // This is not ACK OK packet
- //
- DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);
- }
- Mailbox = GetMailboxPointer ();
- SequenceNo = Mailbox->HostSequenceNo;
- DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo);
- SendPacketWithoutData (AckCommand, SequenceNo);
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand);
- }
- /**
- Decompress the Data in place.
- @param[in, out] Data The compressed data buffer.
- The buffer is assumed large enough to hold the uncompressed data.
- @param[in] Length The length of the compressed data buffer.
- @return The length of the uncompressed data buffer.
- **/
- UINT8
- DecompressDataInPlace (
- IN OUT UINT8 *Data,
- IN UINTN Length
- )
- {
- UINTN Index;
- UINT16 LastChar;
- UINTN LastCharCount;
- UINT8 CurrentChar;
- LastChar = (UINT16)-1;
- LastCharCount = 0;
- for (Index = 0; Index < Length; Index++) {
- CurrentChar = Data[Index];
- if (LastCharCount == 2) {
- LastCharCount = 0;
- CopyMem (&Data[Index + CurrentChar], &Data[Index + 1], Length - Index - 1);
- SetMem (&Data[Index], CurrentChar, (UINT8)LastChar);
- LastChar = (UINT16)-1;
- Index += CurrentChar - 1;
- Length += CurrentChar - 1;
- } else {
- if (LastChar != CurrentChar) {
- LastCharCount = 0;
- }
- LastCharCount++;
- LastChar = CurrentChar;
- }
- }
- ASSERT (Length <= DEBUG_DATA_MAXIMUM_REAL_DATA);
- return (UINT8)Length;
- }
- /**
- Receive valid packet from HOST.
- @param[out] InputPacket Buffer to receive packet.
- @param[out] BreakReceived TRUE means break-in symbol received.
- FALSE means break-in symbol not received.
- @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
- TRUE: Compatible packet received.
- FALSE: Incompatible packet received.
- @param[in] Timeout Time out value to wait for acknowledge from HOST.
- The unit is microsecond.
- @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
- FALSE: Does not Skip time out when reading start symbol.
- @retval RETURN_SUCCESS A valid package was received in InputPacket.
- @retval RETURN_TIMEOUT Timeout occurs.
- **/
- RETURN_STATUS
- ReceivePacket (
- OUT UINT8 *InputPacket,
- OUT BOOLEAN *BreakReceived,
- OUT BOOLEAN *IncompatibilityFlag OPTIONAL,
- IN UINTN Timeout,
- IN BOOLEAN SkipStartSymbol
- )
- {
- DEBUG_PACKET_HEADER *DebugHeader;
- UINTN Received;
- DEBUG_PORT_HANDLE Handle;
- UINT16 Crc;
- UINTN TimeoutForStartSymbol;
- Handle = GetDebugPortHandle ();
- if (SkipStartSymbol) {
- TimeoutForStartSymbol = 0;
- } else {
- TimeoutForStartSymbol = Timeout;
- }
- DebugHeader = (DEBUG_PACKET_HEADER *)InputPacket;
- while (TRUE) {
- //
- // Find the valid start symbol
- //
- Received = DebugAgentReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
- if (Received < sizeof (DebugHeader->StartSymbol)) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugAgentReadBuffer(StartSymbol) timeout\n");
- return RETURN_TIMEOUT;
- }
- if ((DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) && (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_COMPRESS)) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);
- continue;
- }
- //
- // Read Package header till field Length
- //
- 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, "DebugAgentReadBuffer(Command) timeout\n");
- return RETURN_TIMEOUT;
- }
- if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {
- if (IncompatibilityFlag != NULL) {
- //
- // This is one old version debug packet format, set Incompatibility flag
- //
- *IncompatibilityFlag = TRUE;
- } else {
- //
- // Skip the bad small packet
- //
- continue;
- }
- } else {
- //
- // Read the payload data include the CRC field
- //
- Received = DebugAgentReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8)(DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
- if (Received == 0) {
- DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(SequenceNo) timeout\n");
- return RETURN_TIMEOUT;
- }
- //
- // Calculate the CRC of Debug Packet
- //
- Crc = DebugHeader->Crc;
- DebugHeader->Crc = 0;
- if (Crc == CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0)) {
- break;
- }
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);
- }
- }
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);
- if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_COMPRESS) {
- DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
- DebugHeader->Length = DecompressDataInPlace (
- (UINT8 *)(DebugHeader + 1),
- DebugHeader->Length - sizeof (DEBUG_PACKET_HEADER)
- ) + sizeof (DEBUG_PACKET_HEADER);
- }
- return RETURN_SUCCESS;
- }
- /**
- Receive acknowledge packet OK from HOST in specified time.
- @param[in] Command The command type issued by TARGET.
- @param[in] Timeout Time out value to wait for acknowledge from HOST.
- The unit is microsecond.
- @param[out] BreakReceived If BreakReceived is not NULL,
- TRUE is returned if break-in symbol received.
- FALSE is returned if break-in symbol not received.
- @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
- TRUE: Compatible packet received.
- FALSE: Incompatible packet received.
- @retval RETURN_SUCCESS Succeed to receive acknowledge packet from HOST,
- the type of acknowledge packet saved in Ack.
- @retval RETURN_TIMEOUT Specified timeout value was up.
- **/
- RETURN_STATUS
- SendCommandAndWaitForAckOK (
- IN UINT8 Command,
- IN UINTN Timeout,
- OUT BOOLEAN *BreakReceived OPTIONAL,
- OUT BOOLEAN *IncompatibilityFlag OPTIONAL
- )
- {
- RETURN_STATUS Status;
- UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];
- DEBUG_PACKET_HEADER *DebugHeader;
- UINT8 SequenceNo;
- UINT8 HostSequenceNo;
- UINT8 RetryCount;
- RetryCount = 3;
- DebugHeader = (DEBUG_PACKET_HEADER *)InputPacketBuffer;
- Status = RETURN_TIMEOUT;
- while (RetryCount > 0) {
- SequenceNo = GetMailboxPointer ()->SequenceNo;
- HostSequenceNo = GetMailboxPointer ()->HostSequenceNo;
- SendPacketWithoutData (Command, SequenceNo);
- Status = ReceivePacket ((UINT8 *)DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);
- if (Status == RETURN_TIMEOUT) {
- if (Command == DEBUG_COMMAND_INIT_BREAK) {
- RetryCount--;
- } else {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");
- }
- continue;
- }
- ASSERT_EFI_ERROR (Status);
- //
- // Status == RETURN_SUCCESS
- //
- if ((DebugHeader->Command == DEBUG_COMMAND_OK) && (DebugHeader->SequenceNo == SequenceNo)) {
- //
- // Received Ack OK
- //
- UpdateMailboxContent (GetMailboxPointer (), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);
- return Status;
- }
- if ((DebugHeader->Command == DEBUG_COMMAND_GO) && ((DebugHeader->SequenceNo == HostSequenceNo) || (Command == DEBUG_COMMAND_INIT_BREAK))) {
- //
- // Received Old GO
- //
- if (Command == DEBUG_COMMAND_INIT_BREAK) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");
- }
- SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);
- }
- }
- ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);
- return Status;
- }
- /**
- Get current break cause.
- @param[in] Vector Vector value of exception or interrupt.
- @param[in] CpuContext Pointer to save CPU context.
- @return The type of break cause defined by XXXX
- **/
- UINT8
- GetBreakCause (
- IN UINTN Vector,
- IN DEBUG_CPU_CONTEXT *CpuContext
- )
- {
- UINT8 Cause;
- Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;
- switch (Vector) {
- case DEBUG_INT1_VECTOR:
- case DEBUG_INT3_VECTOR:
- if (Vector == DEBUG_INT1_VECTOR) {
- //
- // INT 1
- //
- if ((CpuContext->Dr6 & BIT14) != 0) {
- Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
- //
- // DR6.BIT14 Indicates (when set) that the debug exception was
- // triggered by the single step execution mode.
- // The single-step mode is the highest priority debug exception.
- // This is single step, no need to check DR0, to ensure single step
- // work in PeCoffExtraActionLib (right after triggering a breakpoint
- // to report image load/unload).
- //
- return Cause;
- } else {
- Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;
- }
- } else {
- //
- // INT 3
- //
- Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;
- }
- switch (CpuContext->Dr0) {
- case IMAGE_LOAD_SIGNATURE:
- case IMAGE_UNLOAD_SIGNATURE:
- if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {
- Cause = (UINT8)((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?
- DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);
- }
- break;
- case SOFT_INTERRUPT_SIGNATURE:
- if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {
- Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;
- CpuContext->Dr0 = 0;
- } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {
- Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;
- CpuContext->Dr0 = 0;
- }
- break;
- default:
- break;
- }
- break;
- case DEBUG_TIMER_VECTOR:
- Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;
- break;
- default:
- if (Vector < 20) {
- if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {
- //
- // If stepping command is executing
- //
- Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
- } else {
- Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;
- }
- }
- break;
- }
- return Cause;
- }
- /**
- Copy memory from source to destination with specified width.
- @param[out] Dest A pointer to the destination buffer of the memory copy.
- @param[in] Src A pointer to the source buffer of the memory copy.
- @param[in] Count The number of data with specified width to copy from source to destination.
- @param[in] Width Data width in byte.
- **/
- VOID
- CopyMemByWidth (
- OUT UINT8 *Dest,
- IN UINT8 *Src,
- IN UINT16 Count,
- IN UINT8 Width
- )
- {
- UINT8 *Destination;
- UINT8 *Source;
- INT8 Step;
- if (Src > Dest) {
- Destination = Dest;
- Source = Src;
- Step = Width;
- } else {
- //
- // Copy memory from tail to avoid memory overlap
- //
- Destination = Dest + (Count - 1) * Width;
- Source = Src + (Count - 1) * Width;
- Step = -Width;
- }
- while (Count-- != 0) {
- switch (Width) {
- case 1:
- *(UINT8 *)Destination = MmioRead8 ((UINTN)Source);
- break;
- case 2:
- *(UINT16 *)Destination = MmioRead16 ((UINTN)Source);
- break;
- case 4:
- *(UINT32 *)Destination = MmioRead32 ((UINTN)Source);
- break;
- case 8:
- *(UINT64 *)Destination = MmioRead64 ((UINTN)Source);
- break;
- default:
- ASSERT (FALSE);
- }
- Source += Step;
- Destination += Step;
- }
- }
- /**
- Compress the data buffer but do not modify the original buffer.
- The compressed data is directly send to the debug channel.
- Compressing in place doesn't work because the data may become larger
- during compressing phase. ("3 3 ..." --> "3 3 0 ...")
- The routine is expected to be called three times:
- 1. Compute the length of the compressed data buffer;
- 2. Compute the CRC of the compressed data buffer;
- 3. Compress the data and send to the debug channel.
- @param[in] Handle The debug channel handle to send the compressed data buffer.
- @param[in] Data The data buffer.
- @param[in] Length The length of the data buffer.
- @param[in] Send TRUE to send the compressed data buffer.
- @param[out] CompressedLength Return the length of the compressed data buffer.
- It may be larger than the Length in some cases.
- @param[out] CompressedCrc Return the CRC of the compressed data buffer.
- **/
- VOID
- CompressData (
- IN DEBUG_PORT_HANDLE Handle,
- IN UINT8 *Data,
- IN UINT8 Length,
- IN BOOLEAN Send,
- OUT UINTN *CompressedLength OPTIONAL,
- OUT UINT16 *CompressedCrc OPTIONAL
- )
- {
- UINTN Index;
- UINT8 LastChar;
- UINT8 LastCharCount;
- UINT8 CurrentChar;
- UINTN CompressedIndex;
- ASSERT (Length > 0);
- LastChar = Data[0] + 1; // Just ensure it's different from the first byte.
- LastCharCount = 0;
- for (Index = 0, CompressedIndex = 0; Index <= Length; Index++) {
- if (Index < Length) {
- CurrentChar = Data[Index];
- } else {
- CurrentChar = (UINT8)LastChar + 1; // just ensure it's different from LastChar
- }
- if (LastChar != CurrentChar) {
- if (LastCharCount == 1) {
- CompressedIndex++;
- if (CompressedCrc != NULL) {
- *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);
- }
- if (Send) {
- DebugPortWriteBuffer (Handle, &LastChar, 1);
- }
- } else if (LastCharCount >= 2) {
- CompressedIndex += 3;
- LastCharCount -= 2;
- if (CompressedCrc != NULL) {
- *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);
- *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);
- *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc);
- }
- if (Send) {
- DebugPortWriteBuffer (Handle, &LastChar, 1);
- DebugPortWriteBuffer (Handle, &LastChar, 1);
- DebugPortWriteBuffer (Handle, &LastCharCount, 1);
- }
- }
- LastCharCount = 0;
- }
- LastCharCount++;
- LastChar = CurrentChar;
- }
- if (CompressedLength != NULL) {
- *CompressedLength = CompressedIndex;
- }
- }
- /**
- Read memory with specified width and send packet with response data to HOST.
- @param[in] Data Pointer to response data buffer.
- @param[in] Count The number of data with specified Width.
- @param[in] Width Data width in byte.
- @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
- to minimize the stack usage.
- @retval RETURN_SUCCESS Response data was sent successfully.
- **/
- RETURN_STATUS
- ReadMemoryAndSendResponsePacket (
- IN UINT8 *Data,
- IN UINT16 Count,
- IN UINT8 Width,
- IN DEBUG_PACKET_HEADER *DebugHeader
- )
- {
- RETURN_STATUS Status;
- BOOLEAN LastPacket;
- DEBUG_PORT_HANDLE Handle;
- UINT8 SequenceNo;
- UINTN RemainingDataSize;
- UINT8 CurrentDataSize;
- UINTN CompressedDataSize;
- Handle = GetDebugPortHandle ();
- RemainingDataSize = Count * Width;
- while (TRUE) {
- SequenceNo = GetMailboxPointer ()->HostSequenceNo;
- if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
- //
- // If the remaining data is less one real packet size, this is the last data packet
- //
- CurrentDataSize = (UINT8)RemainingDataSize;
- LastPacket = TRUE;
- DebugHeader->Command = DEBUG_COMMAND_OK;
- } else {
- //
- // Data is too larger to be sent in one packet, calculate the actual data size could
- // be sent in one Maximum data packet
- //
- CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;
- LastPacket = FALSE;
- DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;
- }
- //
- // Construct the rest Debug header
- //
- DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
- DebugHeader->Length = CurrentDataSize + sizeof (DEBUG_PACKET_HEADER);
- DebugHeader->SequenceNo = SequenceNo;
- DebugHeader->Crc = 0;
- CopyMemByWidth ((UINT8 *)(DebugHeader + 1), Data, CurrentDataSize / Width, Width);
- //
- // Compression/decompression support was added since revision 0.4.
- // Revision 0.3 shouldn't compress the packet.
- //
- if (PcdGet32 (PcdTransferProtocolRevision) >= DEBUG_AGENT_REVISION_04) {
- //
- // Get the compressed data size without modifying the packet.
- //
- CompressData (
- Handle,
- (UINT8 *)(DebugHeader + 1),
- CurrentDataSize,
- FALSE,
- &CompressedDataSize,
- NULL
- );
- } else {
- CompressedDataSize = CurrentDataSize;
- }
- if (CompressedDataSize < CurrentDataSize) {
- DebugHeader->Length = (UINT8)CompressedDataSize + sizeof (DEBUG_PACKET_HEADER);
- DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_COMPRESS;
- //
- // Compute the CRC of the packet head without modifying the packet.
- //
- DebugHeader->Crc = CalculateCrc16 ((UINT8 *)DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);
- CompressData (
- Handle,
- (UINT8 *)(DebugHeader + 1),
- CurrentDataSize,
- FALSE,
- NULL,
- &DebugHeader->Crc
- );
- //
- // Send out the packet head.
- //
- DebugPortWriteBuffer (Handle, (UINT8 *)DebugHeader, sizeof (DEBUG_PACKET_HEADER));
- //
- // Compress and send out the packet data.
- //
- CompressData (
- Handle,
- (UINT8 *)(DebugHeader + 1),
- CurrentDataSize,
- TRUE,
- NULL,
- NULL
- );
- } else {
- //
- // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
- //
- DebugHeader->Crc = CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0);
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *)DebugHeader, DebugHeader->Length);
- DebugPortWriteBuffer (Handle, (UINT8 *)DebugHeader, DebugHeader->Length);
- }
- while (TRUE) {
- Status = ReceivePacket ((UINT8 *)DebugHeader, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);
- if (Status == RETURN_TIMEOUT) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");
- break;
- }
- if ((DebugHeader->Command == DEBUG_COMMAND_OK) && (DebugHeader->SequenceNo == SequenceNo) && LastPacket) {
- //
- // If this is the last packet, return RETURN_SUCCESS.
- //
- return RETURN_SUCCESS;
- }
- if ((DebugHeader->Command == DEBUG_COMMAND_CONTINUE) && (DebugHeader->SequenceNo == (UINT8)(SequenceNo + 1))) {
- //
- // Calculate the rest data size
- //
- Data += CurrentDataSize;
- RemainingDataSize -= CurrentDataSize;
- UpdateMailboxContent (GetMailboxPointer (), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);
- break;
- }
- if (DebugHeader->SequenceNo >= SequenceNo) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);
- break;
- }
- }
- }
- }
- /**
- Send packet with response data to HOST.
- @param[in] Data Pointer to response data buffer.
- @param[in] DataSize Size of response data in byte.
- @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
- to minimize the stack usage.
- @retval RETURN_SUCCESS Response data was sent successfully.
- **/
- RETURN_STATUS
- SendDataResponsePacket (
- IN UINT8 *Data,
- IN UINT16 DataSize,
- IN OUT DEBUG_PACKET_HEADER *DebugHeader
- )
- {
- return ReadMemoryAndSendResponsePacket (Data, DataSize, 1, DebugHeader);
- }
- /**
- Try to attach the HOST.
- Send init break packet to HOST:
- If no acknowledge received in specified Timeout, return RETURN_TIMEOUT.
- If received acknowledge, check the revision of HOST.
- Set Attach Flag if attach successfully.
- @param[in] BreakCause Break cause of this break event.
- @param[in] Timeout Time out value to wait for acknowledge from HOST.
- The unit is microsecond.
- @param[out] BreakReceived If BreakReceived is not NULL,
- TRUE is returned if break-in symbol received.
- FALSE is returned if break-in symbol not received.
- **/
- RETURN_STATUS
- AttachHost (
- IN UINT8 BreakCause,
- IN UINTN Timeout,
- OUT BOOLEAN *BreakReceived
- )
- {
- RETURN_STATUS Status;
- DEBUG_PORT_HANDLE Handle;
- BOOLEAN IncompatibilityFlag;
- IncompatibilityFlag = FALSE;
- Handle = GetDebugPortHandle ();
- //
- // Send init break and wait ack in Timeout
- //
- DebugPortWriteBuffer (Handle, (UINT8 *)mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));
- if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
- Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);
- } else {
- Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);
- }
- if (IncompatibilityFlag) {
- //
- // If the incompatible Debug Packet received, the HOST should be running transfer protocol before PcdTransferProtocolRevision.
- // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
- //
- DebugPortWriteBuffer (Handle, (UINT8 *)mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));
- CpuDeadLoop ();
- }
- if (RETURN_ERROR (Status)) {
- DebugPortWriteBuffer (Handle, (UINT8 *)mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));
- } else {
- DebugPortWriteBuffer (Handle, (UINT8 *)mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));
- //
- // Set Attach flag
- //
- SetHostAttached (TRUE);
- }
- return Status;
- }
- /**
- Send Break point packet to HOST.
- Only the first breaking processor could sent BREAK_POINT packet.
- @param[in] BreakCause Break cause of this break event.
- @param[in] ProcessorIndex Processor index value.
- @param[out] BreakReceived If BreakReceived is not NULL,
- TRUE is returned if break-in symbol received.
- FALSE is returned if break-in symbol not received.
- **/
- VOID
- SendBreakPacketToHost (
- IN UINT8 BreakCause,
- IN UINT32 ProcessorIndex,
- OUT BOOLEAN *BreakReceived
- )
- {
- UINT8 InputCharacter;
- DEBUG_PORT_HANDLE Handle;
- Handle = GetDebugPortHandle ();
- if (IsHostAttached ()) {
- DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);
- SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);
- } else {
- DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);
- //
- // If HOST is not attached, try to attach it firstly.
- //
- //
- // Poll Attach symbols from HOST and ack OK
- //
- do {
- DebugAgentReadBuffer (Handle, &InputCharacter, 1, 0);
- } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);
- SendAckPacket (DEBUG_COMMAND_OK);
- //
- // Try to attach HOST
- //
- while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS) {
- }
- }
- }
- /**
- The main function to process communication with HOST.
- It received the command packet from HOST, and sent response data packet to HOST.
- @param[in] Vector Vector value of exception or interrupt.
- @param[in, out] CpuContext Pointer to saved CPU context.
- @param[in] BreakReceived TRUE means break-in symbol received.
- FALSE means break-in symbol not received.
- **/
- VOID
- CommandCommunication (
- IN UINTN Vector,
- IN OUT DEBUG_CPU_CONTEXT *CpuContext,
- IN BOOLEAN BreakReceived
- )
- {
- RETURN_STATUS Status;
- UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];
- DEBUG_PACKET_HEADER *DebugHeader;
- UINT8 Width;
- UINT8 Data8;
- UINT32 Data32;
- UINT64 Data64;
- DEBUG_DATA_READ_MEMORY *MemoryRead;
- DEBUG_DATA_WRITE_MEMORY *MemoryWrite;
- DEBUG_DATA_READ_IO *IoRead;
- DEBUG_DATA_WRITE_IO *IoWrite;
- DEBUG_DATA_READ_REGISTER *RegisterRead;
- DEBUG_DATA_WRITE_REGISTER *RegisterWrite;
- UINT8 *RegisterBuffer;
- DEBUG_DATA_READ_MSR *MsrRegisterRead;
- DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;
- DEBUG_DATA_CPUID *Cpuid;
- DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause;
- DEBUG_DATA_RESPONSE_CPUID CpuidResponse;
- DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;
- DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;
- DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;
- DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;
- BOOLEAN HaltDeferred;
- UINT32 ProcessorIndex;
- DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;
- UINT32 IssuedViewPoint;
- DEBUG_AGENT_MAILBOX *Mailbox;
- UINT8 *AlignedDataPtr;
- ProcessorIndex = 0;
- IssuedViewPoint = 0;
- HaltDeferred = BreakReceived;
- if (MultiProcessorDebugSupport ()) {
- ProcessorIndex = GetProcessorIndex ();
- SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
- if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
- //
- // Only the current view processor could set AgentInProgress Flag.
- //
- IssuedViewPoint = ProcessorIndex;
- }
- }
- if (IssuedViewPoint == ProcessorIndex) {
- //
- // Set AgentInProgress Flag.
- //
- SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);
- }
- while (TRUE) {
- if (MultiProcessorDebugSupport ()) {
- //
- // Check if the current processor is HOST view point
- //
- if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
- if (mDebugMpContext.RunCommandSet) {
- //
- // If HOST view point sets RUN flag, run GO command to leave
- //
- SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
- CommandGo (CpuContext);
- break;
- } else {
- //
- // Run into loop again
- //
- CpuPause ();
- continue;
- }
- }
- }
- AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- DebugHeader = (DEBUG_PACKET_HEADER *)InputPacketBuffer;
- DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");
- Status = ReceivePacket ((UINT8 *)DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);
- if ((Status != RETURN_SUCCESS) || !IS_REQUEST (DebugHeader)) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- continue;
- }
- Mailbox = GetMailboxPointer ();
- if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] against command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
- SendAckPacket (Mailbox->LastAck);
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- continue;
- } else if (DebugHeader->SequenceNo == (UINT8)(Mailbox->HostSequenceNo + 1)) {
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8)DebugHeader->SequenceNo);
- } else {
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid command[%x] against command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- continue;
- }
- //
- // Save CPU content before executing HOST command
- //
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN)&AgentExceptionBuffer.JumpBuffer);
- if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {
- //
- // If HOST command failed, continue to wait for HOST's next command
- // If needed, agent could send exception info to HOST.
- //
- SendAckPacket (DEBUG_COMMAND_ABORT);
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- continue;
- }
- DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);
- switch (DebugHeader->Command) {
- case DEBUG_COMMAND_HALT:
- SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
- HaltDeferred = TRUE;
- BreakReceived = FALSE;
- Status = RETURN_SUCCESS;
- break;
- case DEBUG_COMMAND_RESET:
- SendAckPacket (DEBUG_COMMAND_OK);
- SendAckPacket (DEBUG_COMMAND_OK);
- SendAckPacket (DEBUG_COMMAND_OK);
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- ResetCold ();
- //
- // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
- // PCD can be used if 2 seconds isn't long enough for some platforms.
- //
- MicroSecondDelay (2000000);
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);
- SendAckPacket (DEBUG_COMMAND_TIMEOUT);
- SendAckPacket (DEBUG_COMMAND_TIMEOUT);
- SendAckPacket (DEBUG_COMMAND_TIMEOUT);
- break;
- case DEBUG_COMMAND_GO:
- CommandGo (CpuContext);
- //
- // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
- // If HOST changed Dr0 before GO, we will not change Dr0 here
- //
- Data8 = GetBreakCause (Vector, CpuContext);
- if ((Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD) || (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD)) {
- CpuContext->Dr0 = 0;
- }
- if (!HaltDeferred) {
- //
- // If no HALT command received when being in-active mode
- //
- if (MultiProcessorDebugSupport ()) {
- Data32 = FindNextPendingBreakCpu ();
- if (Data32 != -1) {
- //
- // If there are still others processors being in break state,
- // send OK packet to HOST to finish this go command
- //
- SendAckPacket (DEBUG_COMMAND_OK);
- CpuPause ();
- //
- // Set current view to the next breaking processor
- //
- mDebugMpContext.ViewPointIndex = Data32;
- mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
- SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
- //
- // Send break packet to HOST to let HOST break again
- //
- SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);
- //
- // Continue to run into loop to read command packet from HOST
- //
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- break;
- }
- //
- // If no else processor break, set stop bitmask,
- // and set Running flag for all processors.
- //
- SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
- SetCpuRunningFlag (TRUE);
- CpuPause ();
- //
- // Wait for all processors are in running state
- //
- while (TRUE) {
- if (IsAllCpuRunning ()) {
- break;
- }
- }
- //
- // Set BSP to be current view point.
- //
- SetDebugViewPoint (mDebugMpContext.BspIndex);
- CpuPause ();
- //
- // Clear breaking processor index and running flag
- //
- mDebugMpContext.BreakAtCpuIndex = (UINT32)(-1);
- SetCpuRunningFlag (FALSE);
- }
- //
- // Send OK packet to HOST to finish this go command
- //
- SendAckPacket (DEBUG_COMMAND_OK);
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- if (!IsHostAttached ()) {
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);
- }
- return;
- } else {
- //
- // If received HALT command, need to defer the GO command
- //
- SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
- HaltDeferred = FALSE;
- Vector = DEBUG_TIMER_VECTOR;
- }
- break;
- case DEBUG_COMMAND_BREAK_CAUSE:
- BreakCause.StopAddress = CpuContext->Eip;
- if (MultiProcessorDebugSupport () && (ProcessorIndex != mDebugMpContext.BreakAtCpuIndex)) {
- BreakCause.Cause = GetBreakCause (DEBUG_TIMER_VECTOR, CpuContext);
- } else {
- BreakCause.Cause = GetBreakCause (Vector, CpuContext);
- }
- SendDataResponsePacket ((UINT8 *)&BreakCause, (UINT16)sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE), DebugHeader);
- break;
- case DEBUG_COMMAND_SET_HW_BREAKPOINT:
- SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *)(DebugHeader + 1));
- SendAckPacket (DEBUG_COMMAND_OK);
- break;
- case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
- ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *)(DebugHeader + 1));
- SendAckPacket (DEBUG_COMMAND_OK);
- break;
- case DEBUG_COMMAND_SINGLE_STEPPING:
- CommandStepping (CpuContext);
- //
- // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
- // If HOST changed Dr0 before GO, we will not change Dr0 here
- //
- Data8 = GetBreakCause (Vector, CpuContext);
- if ((Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD) || (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD)) {
- CpuContext->Dr0 = 0;
- }
- mDebugMpContext.BreakAtCpuIndex = (UINT32)(-1);
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- //
- // Executing stepping command directly without sending ACK packet,
- // ACK packet will be sent after stepping done.
- //
- return;
- case DEBUG_COMMAND_SET_SW_BREAKPOINT:
- Data64 = (UINTN)(((DEBUG_DATA_SET_SW_BREAKPOINT *)(DebugHeader + 1))->Address);
- Data8 = *(UINT8 *)(UINTN)Data64;
- *(UINT8 *)(UINTN)Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
- Status = SendDataResponsePacket ((UINT8 *)&Data8, (UINT16)sizeof (UINT8), DebugHeader);
- break;
- case DEBUG_COMMAND_READ_MEMORY:
- MemoryRead = (DEBUG_DATA_READ_MEMORY *)(DebugHeader + 1);
- Status = ReadMemoryAndSendResponsePacket ((UINT8 *)(UINTN)MemoryRead->Address, MemoryRead->Count, MemoryRead->Width, DebugHeader);
- break;
- case DEBUG_COMMAND_WRITE_MEMORY:
- MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *)(DebugHeader + 1);
- //
- // Copy data into one memory with 8-byte alignment address
- //
- AlignedDataPtr = ALIGN_POINTER ((UINT8 *)&MemoryWrite->Data, sizeof (UINT64));
- if (AlignedDataPtr != (UINT8 *)&MemoryWrite->Data) {
- CopyMem (AlignedDataPtr, (UINT8 *)&MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);
- }
- CopyMemByWidth ((UINT8 *)(UINTN)MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);
- SendAckPacket (DEBUG_COMMAND_OK);
- break;
- case DEBUG_COMMAND_READ_IO:
- IoRead = (DEBUG_DATA_READ_IO *)(DebugHeader + 1);
- switch (IoRead->Width) {
- case 1:
- Data64 = IoRead8 ((UINTN)IoRead->Port);
- break;
- case 2:
- Data64 = IoRead16 ((UINTN)IoRead->Port);
- break;
- case 4:
- Data64 = IoRead32 ((UINTN)IoRead->Port);
- break;
- case 8:
- Data64 = IoRead64 ((UINTN)IoRead->Port);
- break;
- default:
- Data64 = (UINT64)-1;
- }
- Status = SendDataResponsePacket ((UINT8 *)&Data64, IoRead->Width, DebugHeader);
- break;
- case DEBUG_COMMAND_WRITE_IO:
- IoWrite = (DEBUG_DATA_WRITE_IO *)(DebugHeader + 1);
- switch (IoWrite->Width) {
- case 1:
- Data64 = IoWrite8 ((UINTN)IoWrite->Port, *(UINT8 *)&IoWrite->Data);
- break;
- case 2:
- Data64 = IoWrite16 ((UINTN)IoWrite->Port, *(UINT16 *)&IoWrite->Data);
- break;
- case 4:
- Data64 = IoWrite32 ((UINTN)IoWrite->Port, *(UINT32 *)&IoWrite->Data);
- break;
- case 8:
- Data64 = IoWrite64 ((UINTN)IoWrite->Port, *(UINT64 *)&IoWrite->Data);
- break;
- default:
- Data64 = (UINT64)-1;
- }
- SendAckPacket (DEBUG_COMMAND_OK);
- break;
- case DEBUG_COMMAND_READ_ALL_REGISTERS:
- Status = SendDataResponsePacket ((UINT8 *)CpuContext, sizeof (*CpuContext), DebugHeader);
- break;
- case DEBUG_COMMAND_READ_REGISTER:
- RegisterRead = (DEBUG_DATA_READ_REGISTER *)(DebugHeader + 1);
- if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {
- RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);
- Status = SendDataResponsePacket (RegisterBuffer, Width, DebugHeader);
- } else {
- Status = RETURN_UNSUPPORTED;
- }
- break;
- case DEBUG_COMMAND_WRITE_REGISTER:
- RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *)(DebugHeader + 1);
- if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {
- RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);
- ASSERT (Width == RegisterWrite->Length);
- CopyMem (RegisterBuffer, RegisterWrite->Data, Width);
- SendAckPacket (DEBUG_COMMAND_OK);
- } else {
- Status = RETURN_UNSUPPORTED;
- }
- break;
- case DEBUG_COMMAND_ARCH_MODE:
- Data8 = DEBUG_ARCH_SYMBOL;
- Status = SendDataResponsePacket ((UINT8 *)&Data8, (UINT16)sizeof (UINT8), DebugHeader);
- break;
- case DEBUG_COMMAND_READ_MSR:
- MsrRegisterRead = (DEBUG_DATA_READ_MSR *)(DebugHeader + 1);
- Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
- Status = SendDataResponsePacket ((UINT8 *)&Data64, (UINT16)sizeof (UINT64), DebugHeader);
- break;
- case DEBUG_COMMAND_WRITE_MSR:
- MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *)(DebugHeader + 1);
- AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
- SendAckPacket (DEBUG_COMMAND_OK);
- break;
- case DEBUG_COMMAND_SET_DEBUG_SETTING:
- Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));
- if (Status == RETURN_SUCCESS) {
- SendAckPacket (DEBUG_COMMAND_OK);
- }
- break;
- case DEBUG_COMMAND_GET_REVISION:
- DebugAgentRevision.Revision = PcdGet32 (PcdTransferProtocolRevision);
- DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
- Status = SendDataResponsePacket ((UINT8 *)&DebugAgentRevision, (UINT16)sizeof (DEBUG_DATA_RESPONSE_GET_REVISION), DebugHeader);
- break;
- case DEBUG_COMMAND_GET_EXCEPTION:
- Exception.ExceptionNum = (UINT8)Vector;
- Exception.ExceptionData = (UINT32)CpuContext->ExceptionData;
- Status = SendDataResponsePacket ((UINT8 *)&Exception, (UINT16)sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION), DebugHeader);
- break;
- case DEBUG_COMMAND_SET_VIEWPOINT:
- SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *)(DebugHeader + 1);
- if (MultiProcessorDebugSupport ()) {
- if (IsCpuStopped (SetViewPoint->ViewPoint)) {
- SetDebugViewPoint (SetViewPoint->ViewPoint);
- SendAckPacket (DEBUG_COMMAND_OK);
- } else {
- //
- // If CPU is not halted
- //
- SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
- }
- } else if (SetViewPoint->ViewPoint == 0) {
- SendAckPacket (DEBUG_COMMAND_OK);
- } else {
- SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
- }
- break;
- case DEBUG_COMMAND_GET_VIEWPOINT:
- Data32 = mDebugMpContext.ViewPointIndex;
- SendDataResponsePacket ((UINT8 *)&Data32, (UINT16)sizeof (UINT32), DebugHeader);
- break;
- case DEBUG_COMMAND_MEMORY_READY:
- Data8 = (UINT8)GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);
- SendDataResponsePacket (&Data8, (UINT16)sizeof (UINT8), DebugHeader);
- break;
- case DEBUG_COMMAND_DETACH:
- SetHostAttached (FALSE);
- SendAckPacket (DEBUG_COMMAND_OK);
- break;
- case DEBUG_COMMAND_CPUID:
- Cpuid = (DEBUG_DATA_CPUID *)(DebugHeader + 1);
- AsmCpuidEx (
- Cpuid->Eax,
- Cpuid->Ecx,
- &CpuidResponse.Eax,
- &CpuidResponse.Ebx,
- &CpuidResponse.Ecx,
- &CpuidResponse.Edx
- );
- SendDataResponsePacket ((UINT8 *)&CpuidResponse, (UINT16)sizeof (CpuidResponse), DebugHeader);
- break;
- case DEBUG_COMMAND_SEARCH_SIGNATURE:
- SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *)(DebugHeader + 1);
- if ((SearchSignature->Alignment != 0) &&
- (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))
- )
- {
- if (SearchSignature->Positive) {
- for (
- Data64 = ALIGN_VALUE ((UINTN)SearchSignature->Start, SearchSignature->Alignment);
- Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;
- Data64 += SearchSignature->Alignment
- )
- {
- if (CompareMem ((VOID *)(UINTN)Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {
- break;
- }
- }
- if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {
- Data64 = (UINT64)-1;
- }
- } else {
- for (
- Data64 = ALIGN_VALUE ((UINTN)SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);
- Data64 >= SearchSignature->Start - SearchSignature->Count;
- Data64 -= SearchSignature->Alignment
- )
- {
- if (CompareMem ((VOID *)(UINTN)Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {
- break;
- }
- }
- if (Data64 < SearchSignature->Start - SearchSignature->Count) {
- Data64 = (UINT64)-1;
- }
- }
- SendDataResponsePacket ((UINT8 *)&Data64, (UINT16)sizeof (Data64), DebugHeader);
- } else {
- Status = RETURN_UNSUPPORTED;
- }
- break;
- default:
- SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
- break;
- }
- if (Status == RETURN_UNSUPPORTED) {
- SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
- } else if (Status != RETURN_SUCCESS) {
- SendAckPacket (DEBUG_COMMAND_ABORT);
- }
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- CpuPause ();
- }
- }
- /**
- C function called in interrupt handler.
- @param[in] Vector Vector value of exception or interrupt.
- @param[in] CpuContext Pointer to save CPU context.
- **/
- VOID
- EFIAPI
- InterruptProcess (
- IN UINT32 Vector,
- IN DEBUG_CPU_CONTEXT *CpuContext
- )
- {
- UINT8 InputCharacter;
- UINT8 BreakCause;
- UINTN SavedEip;
- BOOLEAN BreakReceived;
- UINT32 ProcessorIndex;
- UINT32 CurrentDebugTimerInitCount;
- DEBUG_PORT_HANDLE Handle;
- UINT8 Data8;
- UINT8 *Al;
- UINT32 IssuedViewPoint;
- DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;
- InputCharacter = 0;
- ProcessorIndex = 0;
- IssuedViewPoint = 0;
- BreakReceived = FALSE;
- if (mSkipBreakpoint) {
- //
- // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
- //
- if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {
- DebugPortWriteBuffer (GetDebugPortHandle (), (UINT8 *)mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));
- return;
- }
- }
- if (MultiProcessorDebugSupport ()) {
- ProcessorIndex = GetProcessorIndex ();
- //
- // If this processor has already halted before, need to check it later
- //
- if (IsCpuStopped (ProcessorIndex)) {
- IssuedViewPoint = ProcessorIndex;
- }
- }
- if ((IssuedViewPoint == ProcessorIndex) && (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1)) {
- //
- // Check if this exception is issued by Debug Agent itself
- // If yes, fill the debug agent exception buffer and LongJump() back to
- // the saved CPU content in CommandCommunication()
- // If exception is issued when executing Stepping, will be handled in
- // exception handle procedure.
- //
- if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {
- DebugAgentMsgPrint (
- DEBUG_AGENT_ERROR,
- "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n",
- Vector,
- (UINTN)CpuContext->Eip
- );
- ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *)(UINTN)GetMailboxPointer ()->ExceptionBufferPointer;
- ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8)Vector;
- ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32)CpuContext->ExceptionData;
- LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);
- }
- }
- if (MultiProcessorDebugSupport ()) {
- //
- // If RUN command is executing, wait for it done.
- //
- while (mDebugMpContext.RunCommandSet) {
- CpuPause ();
- }
- }
- Handle = GetDebugPortHandle ();
- BreakCause = GetBreakCause (Vector, CpuContext);
- switch (Vector) {
- case DEBUG_INT1_VECTOR:
- case DEBUG_INT3_VECTOR:
- switch (BreakCause) {
- case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:
- if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
- //
- // Try to connect HOST, return if fails
- //
- break;
- }
- CommandCommunication (Vector, CpuContext, BreakReceived);
- break;
- case DEBUG_DATA_BREAK_CAUSE_STEPPING:
- //
- // Stepping is finished, send Ack package.
- //
- if (MultiProcessorDebugSupport ()) {
- mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
- }
- //
- // Clear Stepping Flag and restore EFLAGS.IF
- //
- CommandSteppingCleanup (CpuContext);
- SendAckPacket (DEBUG_COMMAND_OK);
- CommandCommunication (Vector, CpuContext, BreakReceived);
- break;
- case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:
- //
- // Memory is ready
- //
- SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);
- CommandCommunication (Vector, CpuContext, BreakReceived);
- break;
- case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:
- case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:
- //
- // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
- //
- Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);
- *Al = DEBUG_AGENT_IMAGE_CONTINUE;
- if (!IsHostAttached ()) {
- //
- // If HOST is not connected for image load/unload, return
- //
- break;
- }
- //
- // Continue to run the following common code
- //
- case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:
- case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:
- default:
- //
- // Send Break packet to HOST
- //
- AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- //
- // Only the first breaking processor could send BREAK_POINT to HOST
- //
- if (IsFirstBreakProcessor (ProcessorIndex)) {
- SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
- }
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- if (Vector == DEBUG_INT3_VECTOR) {
- //
- // go back address located "0xCC"
- //
- CpuContext->Eip--;
- SavedEip = CpuContext->Eip;
- CommandCommunication (Vector, CpuContext, BreakReceived);
- if ((SavedEip == CpuContext->Eip) &&
- (*(UINT8 *)(UINTN)CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL))
- {
- //
- // If this is not a software breakpoint set by HOST,
- // restore EIP
- //
- CpuContext->Eip++;
- }
- } else {
- CommandCommunication (Vector, CpuContext, BreakReceived);
- }
- break;
- }
- break;
- case DEBUG_TIMER_VECTOR:
- AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- if (MultiProcessorDebugSupport ()) {
- if (DebugAgentIsBsp (ProcessorIndex)) {
- //
- // If current processor is BSP, check Apic timer's init count if changed,
- // it may be re-written when switching BSP.
- // If it changed, re-initialize debug timer
- //
- CurrentDebugTimerInitCount = GetApicTimerInitCount ();
- if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
- InitializeDebugTimer (NULL, FALSE);
- SaveAndSetDebugTimerInterrupt (TRUE);
- }
- }
- if (!DebugAgentIsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- //
- // If current processor is not BSP or this is one IPI sent by AP
- //
- if (mDebugMpContext.BreakAtCpuIndex != (UINT32)(-1)) {
- CommandCommunication (Vector, CpuContext, FALSE);
- }
- //
- // Clear EOI before exiting interrupt process routine.
- //
- SendApicEoi ();
- break;
- }
- }
- //
- // Only BSP could run here
- //
- while (TRUE) {
- //
- // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
- // If yes, go into communication mode with HOST.
- // If no, exit interrupt process.
- //
- if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {
- break;
- }
- if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||
- (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||
- (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))
- )
- {
- DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);
- //
- // Ack OK for break-in symbol
- //
- SendAckPacket (DEBUG_COMMAND_OK);
- //
- // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
- //
- if (InputCharacter == DEBUG_COMMAND_GO) {
- break;
- }
- if (!IsHostAttached ()) {
- //
- // Try to attach HOST, if no ack received after 200ms, return
- //
- if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
- break;
- }
- }
- if (MultiProcessorDebugSupport ()) {
- if (FindNextPendingBreakCpu () != -1) {
- SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
- } else {
- HaltOtherProcessors (ProcessorIndex);
- }
- }
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- CommandCommunication (Vector, CpuContext, BreakReceived);
- AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- break;
- }
- }
- //
- // Clear EOI before exiting interrupt process routine.
- //
- SendApicEoi ();
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- break;
- default:
- if (Vector <= DEBUG_EXCEPT_SIMD) {
- DebugAgentMsgPrint (
- DEBUG_AGENT_ERROR,
- "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n",
- Vector,
- (UINTN)CpuContext->Eip
- );
- if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
- //
- // If exception happened when executing Stepping, send Ack package.
- // HOST consider Stepping command was finished.
- //
- if (MultiProcessorDebugSupport ()) {
- mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
- }
- //
- // Clear Stepping flag and restore EFLAGS.IF
- //
- CommandSteppingCleanup (CpuContext);
- SendAckPacket (DEBUG_COMMAND_OK);
- } else {
- //
- // Exception occurs, send Break packet to HOST
- //
- AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- //
- // Only the first breaking processor could send BREAK_POINT to HOST
- //
- if (IsFirstBreakProcessor (ProcessorIndex)) {
- SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
- }
- ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- }
- CommandCommunication (Vector, CpuContext, BreakReceived);
- }
- break;
- }
- if (MultiProcessorDebugSupport ()) {
- //
- // Clear flag and wait for all processors run here
- //
- SetIpiSentByApFlag (FALSE);
- while (mDebugMpContext.RunCommandSet) {
- CpuPause ();
- }
- //
- // Only current (view) processor could clean up AgentInProgress flag.
- //
- if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
- IssuedViewPoint = mDebugMpContext.ViewPointIndex;
- }
- }
- if ((IssuedViewPoint == ProcessorIndex) && (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1)) {
- //
- // If the command is not stepping, clean up AgentInProgress flag
- //
- SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);
- }
- return;
- }
|