1 /** @file
2   Debug Port Library implementation based on usb3 debug port.
3 
4   Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "DebugCommunicationLibUsb3Internal.h"
10 
11 UINT16   mString0Desc[] = {
12   //  String Descriptor Type + Length
13   ( USB_DESC_TYPE_STRING << 8 ) + STRING0_DESC_LEN,
14   0x0409
15 };
16 
17 UINT16   mManufacturerStrDesc[] = {
18   //  String Descriptor Type + Length
19   ( USB_DESC_TYPE_STRING << 8 ) + MANU_DESC_LEN,
20   'I', 'n', 't', 'e', 'l'
21 };
22 
23 UINT16   mProductStrDesc[] = {
24   //  String Descriptor Type + Length
25   ( USB_DESC_TYPE_STRING << 8 ) +  PRODUCT_DESC_LEN,
26   'U', 'S', 'B', ' ', '3', '.', '0', ' ', 'D', 'e', 'b', 'u', 'g', ' ', 'C', 'a', 'b', 'l', 'e'
27 };
28 
29 UINT16   mSerialNumberStrDesc[] = {
30   //  String Descriptor Type + Length
31   ( USB_DESC_TYPE_STRING << 8 ) +  SERIAL_DESC_LEN,
32   '1'
33 };
34 
35 /**
36   Sets bits as per the enabled bit positions in the mask.
37 
38   @param[in, out] Register    UINTN register
39   @param[in]      BitMask     32-bit mask
40 **/
41 VOID
XhcSetR32Bit(IN OUT UINTN Register,IN UINT32 BitMask)42 XhcSetR32Bit(
43   IN OUT  UINTN  Register,
44   IN      UINT32 BitMask
45   )
46 {
47   UINT32    RegisterValue;
48 
49   RegisterValue = MmioRead32 (Register);
50   RegisterValue |= (UINT32)(BitMask);
51   MmioWrite32 (Register, RegisterValue);
52 }
53 
54 /**
55   Clears bits as per the enabled bit positions in the mask.
56 
57   @param[in, out] Register    UINTN register
58   @param[in]      BitMask     32-bit mask
59 **/
60 VOID
XhcClearR32Bit(IN OUT UINTN Register,IN UINT32 BitMask)61 XhcClearR32Bit(
62   IN OUT  UINTN  Register,
63   IN      UINT32 BitMask
64   )
65 {
66   UINT32    RegisterValue;
67 
68   RegisterValue = MmioRead32 (Register);
69   RegisterValue &= ~BitMask;
70   MmioWrite32 (Register, RegisterValue);
71 }
72 
73 /**
74   Write the data to the XHCI debug register.
75 
76   @param  Handle       Debug port handle.
77   @param  Offset       The offset of the debug register.
78   @param  Data         The data to write.
79 
80 **/
81 VOID
XhcWriteDebugReg(IN USB3_DEBUG_PORT_HANDLE * Handle,IN UINT32 Offset,IN UINT32 Data)82 XhcWriteDebugReg (
83   IN USB3_DEBUG_PORT_HANDLE  *Handle,
84   IN UINT32                  Offset,
85   IN UINT32                  Data
86   )
87 {
88   EFI_PHYSICAL_ADDRESS  DebugCapabilityBase;
89 
90   DebugCapabilityBase = Handle->DebugCapabilityBase;
91   MmioWrite32 ((UINTN)(DebugCapabilityBase + Offset), Data);
92 
93   return;
94 }
95 
96 /**
97   Read XHCI debug register.
98 
99   @param  Handle       Debug port handle.
100   @param  Offset       The offset of the runtime register.
101 
102   @return The register content read
103 
104 **/
105 UINT32
XhcReadDebugReg(IN USB3_DEBUG_PORT_HANDLE * Handle,IN UINT32 Offset)106 XhcReadDebugReg (
107   IN  USB3_DEBUG_PORT_HANDLE *Handle,
108   IN  UINT32                 Offset
109   )
110 {
111   UINT32                  Data;
112   EFI_PHYSICAL_ADDRESS    DebugCapabilityBase;
113 
114   DebugCapabilityBase = Handle->DebugCapabilityBase;
115   Data = MmioRead32 ((UINTN)(DebugCapabilityBase + Offset));
116 
117   return Data;
118 }
119 
120 /**
121   Set one bit of the debug register while keeping other bits.
122 
123   @param  Handle       Debug port handle.
124   @param  Offset       The offset of the debug register.
125   @param  Bit          The bit mask of the register to set.
126 
127 **/
128 VOID
XhcSetDebugRegBit(IN USB3_DEBUG_PORT_HANDLE * Handle,IN UINT32 Offset,IN UINT32 Bit)129 XhcSetDebugRegBit (
130   IN USB3_DEBUG_PORT_HANDLE   *Handle,
131   IN UINT32                   Offset,
132   IN UINT32                   Bit
133   )
134 {
135   UINT32                  Data;
136 
137   Data  = XhcReadDebugReg (Handle, Offset);
138   Data |= Bit;
139   XhcWriteDebugReg (Handle, Offset, Data);
140 }
141 
142 /**
143   Clear one bit of the debug register while keeping other bits.
144 
145   @param  Handle       Debug port handle.
146   @param  Offset       The offset of the debug register.
147   @param  Bit          The bit mask of the register to clear.
148 
149 **/
150 VOID
XhcClearDebugRegBit(IN USB3_DEBUG_PORT_HANDLE * Handle,IN UINT32 Offset,IN UINT32 Bit)151 XhcClearDebugRegBit (
152   IN USB3_DEBUG_PORT_HANDLE   *Handle,
153   IN UINT32                   Offset,
154   IN UINT32                   Bit
155   )
156 {
157   UINT32                  Data;
158 
159   Data  = XhcReadDebugReg (Handle, Offset);
160   Data  &= ~Bit;
161   XhcWriteDebugReg (Handle, Offset, Data);
162 }
163 
164 /**
165   Program and eanble XHCI MMIO base address.
166 
167   @return XHCI MMIO base address.
168 
169 **/
170 EFI_PHYSICAL_ADDRESS
ProgramXhciBaseAddress(VOID)171 ProgramXhciBaseAddress (
172   VOID
173   )
174 {
175   UINT16                      PciCmd;
176   UINT32                      Low;
177   UINT32                      High;
178   EFI_PHYSICAL_ADDRESS        XhciMmioBase;
179 
180   Low = PciRead32 (PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
181   High = PciRead32 (PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + 4);
182   XhciMmioBase = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);
183   XhciMmioBase &= XHCI_BASE_ADDRESS_64_BIT_MASK;
184 
185   if ((XhciMmioBase == 0) || (XhciMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
186     XhciMmioBase = PcdGet64(PcdUsbXhciMemorySpaceBase);
187     PciWrite32(PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, XhciMmioBase & 0xFFFFFFFF);
188     PciWrite32(PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + 4, (RShiftU64 (XhciMmioBase, 32) & 0xFFFFFFFF));
189   }
190 
191   PciCmd = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET);
192   if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
193     PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;
194     PciWrite16(PcdGet32(PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);
195   }
196 
197   return XhciMmioBase;
198 }
199 
200 /**
201   Update XHC MMIO base address when MMIO base address is changed.
202 
203   @param  Handle          Debug port handle.
204   @param  XhciMmioBase    XHCI MMIO base address.
205 
206 **/
207 VOID
UpdateXhcResource(IN OUT USB3_DEBUG_PORT_HANDLE * Handle,IN EFI_PHYSICAL_ADDRESS XhciMmioBase)208 UpdateXhcResource (
209   IN OUT USB3_DEBUG_PORT_HANDLE            *Handle,
210   IN EFI_PHYSICAL_ADDRESS                   XhciMmioBase
211   )
212 {
213   if (Handle == NULL) {
214     return;
215   }
216 
217   //
218   // Need fix Handle data according to new XHCI MMIO base address.
219   //
220   Handle->XhciMmioBase        = XhciMmioBase;
221   Handle->DebugCapabilityBase = XhciMmioBase + Handle->DebugCapabilityOffset;
222   Handle->XhciOpRegister      = XhciMmioBase + MmioRead8 ((UINTN)XhciMmioBase);
223 }
224 
225 /**
226   Calculate the usb debug port bar address.
227 
228   @param  Handle             Debug port handle.
229 
230   @retval RETURN_UNSUPPORTED The usb host controller does not support usb debug port capability.
231   @retval RETURN_SUCCESS     Get bar and offset successfully.
232 
233 **/
234 RETURN_STATUS
235 EFIAPI
CalculateUsbDebugPortMmioBase(USB3_DEBUG_PORT_HANDLE * Handle)236 CalculateUsbDebugPortMmioBase (
237   USB3_DEBUG_PORT_HANDLE          *Handle
238  )
239 {
240   UINT16                          VendorId;
241   UINT16                          DeviceId;
242   UINT8                           ProgInterface;
243   UINT8                           SubClassCode;
244   UINT8                           BaseCode;
245   BOOLEAN                         Flag;
246   UINT32                          Capability;
247   EFI_PHYSICAL_ADDRESS            CapabilityPointer;
248   UINT8                           CapLength;
249 
250   if (Handle->Initialized != USB3DBG_UNINITIALIZED) {
251     if (Handle->Initialized == USB3DBG_NO_DBG_CAB) {
252       return RETURN_UNSUPPORTED;
253     } else {
254       return RETURN_SUCCESS;
255     }
256   }
257 
258   VendorId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_VENDOR_ID_OFFSET);
259   DeviceId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_DEVICE_ID_OFFSET);
260 
261   if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {
262     goto Done;
263   }
264 
265   ProgInterface = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET);
266   SubClassCode  = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET + 1);
267   BaseCode      = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET + 2);
268 
269   if ((ProgInterface != PCI_IF_XHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {
270     goto Done;
271   }
272 
273   CapLength = MmioRead8 ((UINTN) Handle->XhciMmioBase);
274 
275   //
276   // Get capability pointer from HCCPARAMS at offset 0x10
277   //
278   CapabilityPointer = Handle->XhciMmioBase + (MmioRead32 ((UINTN)(Handle->XhciMmioBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
279 
280   //
281   // Search XHCI debug capability
282   //
283   Flag = FALSE;
284   Capability = MmioRead32 ((UINTN)CapabilityPointer);
285   while (TRUE) {
286     if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
287       Flag = TRUE;
288       break;
289     }
290     if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
291       //
292       // Reach the end of capability list, quit
293       //
294       break;
295     }
296     CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
297     Capability = MmioRead32 ((UINTN)CapabilityPointer);
298   }
299 
300   if (!Flag) {
301     goto Done;
302   }
303 
304   //
305   // USB3 debug capability is supported.
306   //
307   Handle->DebugCapabilityBase   = CapabilityPointer;
308   Handle->DebugCapabilityOffset = CapabilityPointer - Handle->XhciMmioBase;
309   Handle->XhciOpRegister        = Handle->XhciMmioBase + CapLength;
310   Handle->DebugSupport = TRUE;
311   Handle->Initialized = USB3DBG_DBG_CAB;
312   return RETURN_SUCCESS;
313 
314 Done:
315   Handle->Initialized = USB3DBG_NO_DBG_CAB;
316   return RETURN_UNSUPPORTED;
317 }
318 
319 /**
320   Check if it needs to re-initialize usb debug port hardware.
321 
322   During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
323   whether the usb debug port hardware configuration is changed. Such case can be triggered by
324   Pci bus resource allocation and so on.
325 
326   @param  Handle           Debug port handle.
327 
328   @retval TRUE             The usb debug port hardware configuration is changed.
329   @retval FALSE            The usb debug port hardware configuration is not changed.
330 
331 **/
332 BOOLEAN
333 EFIAPI
NeedReinitializeHardware(IN USB3_DEBUG_PORT_HANDLE * Handle)334 NeedReinitializeHardware(
335   IN USB3_DEBUG_PORT_HANDLE *Handle
336   )
337 {
338   BOOLEAN                 Result;
339   volatile UINT32         Dcctrl;
340 
341   Result = FALSE;
342 
343   //
344   // If DCE bit, it means USB3 debug is not enabled.
345   //
346   Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
347   if ((Dcctrl & BIT0) == 0) {
348     Result = TRUE;
349   } else if (!Handle->Ready) {
350     Handle->Ready = TRUE;
351     Handle->Initialized = USB3DBG_ENABLED;
352   }
353 
354   return Result;
355 }
356 
357 /**
358   Create XHCI event ring.
359 
360   @param  Handle              Debug port handle.
361   @param  EventRing           The created event ring.
362 
363 **/
364 EFI_STATUS
CreateEventRing(IN USB3_DEBUG_PORT_HANDLE * Handle,OUT EVENT_RING * EventRing)365 CreateEventRing (
366   IN  USB3_DEBUG_PORT_HANDLE     *Handle,
367   OUT EVENT_RING                 *EventRing
368   )
369 {
370   VOID                        *Buf;
371   EVENT_RING_SEG_TABLE_ENTRY  *ERSTBase;
372 
373   ASSERT (EventRing != NULL);
374 
375   //
376   // Allocate Event Ring
377   //
378   Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
379   ASSERT (Buf != NULL);
380   ASSERT (((UINTN) Buf & 0x3F) == 0);
381   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
382 
383   EventRing->EventRingSeg0    = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
384   EventRing->TrbNumber        = EVENT_RING_TRB_NUMBER;
385   EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
386   EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
387 
388   //
389   // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
390   // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
391   //
392   EventRing->EventRingCCS = 1;
393 
394   //
395   // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
396   //
397   Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
398   ASSERT (Buf != NULL);
399   ASSERT (((UINTN) Buf & 0x3F) == 0);
400   ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
401 
402   ERSTBase              = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;
403   EventRing->ERSTBase   = (EFI_PHYSICAL_ADDRESS)(UINTN) ERSTBase;
404 
405   //
406   // Fill Event Segment address
407   //
408   ERSTBase->PtrLo       = XHC_LOW_32BIT (EventRing->EventRingSeg0);
409   ERSTBase->PtrHi       = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
410   ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
411 
412   //
413   // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
414   //
415   XhcWriteDebugReg (
416     Handle,
417     XHC_DC_DCERDP,
418     XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
419     );
420 
421   XhcWriteDebugReg (
422     Handle,
423     XHC_DC_DCERDP + 4,
424     XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
425     );
426 
427   //
428   // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
429   //
430   XhcWriteDebugReg (
431     Handle,
432     XHC_DC_DCERSTBA,
433     XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
434     );
435 
436   XhcWriteDebugReg (
437     Handle,
438     XHC_DC_DCERSTBA + 4,
439     XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
440     );
441 
442   //
443   // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
444   //
445   XhcWriteDebugReg (
446     Handle,
447     XHC_DC_DCERSTSZ,
448     ERST_NUMBER
449     );
450   return EFI_SUCCESS;
451 }
452 
453 /**
454   Create XHCI transfer ring.
455 
456   @param  Handle            Debug port handle.
457   @param  TrbNum            The number of TRB in the ring.
458   @param  TransferRing      The created transfer ring.
459 
460 **/
461 VOID
CreateTransferRing(IN USB3_DEBUG_PORT_HANDLE * Handle,IN UINT32 TrbNum,OUT TRANSFER_RING * TransferRing)462 CreateTransferRing (
463   IN  USB3_DEBUG_PORT_HANDLE      *Handle,
464   IN  UINT32                      TrbNum,
465   OUT TRANSFER_RING               *TransferRing
466   )
467 {
468   VOID                  *Buf;
469   LINK_TRB              *EndTrb;
470 
471   Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);
472   ASSERT (Buf != NULL);
473   ASSERT (((UINTN) Buf & 0xF) == 0);
474   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
475 
476   TransferRing->RingSeg0     = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
477   TransferRing->TrbNumber    = TrbNum;
478   TransferRing->RingEnqueue  = TransferRing->RingSeg0;
479   TransferRing->RingDequeue  = TransferRing->RingSeg0;
480   TransferRing->RingPCS      = 1;
481   //
482   // 4.9.2 Transfer Ring Management
483   // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
484   // point to the first TRB in the ring.
485   //
486   EndTrb        = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
487   EndTrb->Type  = TRB_TYPE_LINK;
488   EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
489   EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
490   //
491   // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
492   //
493   EndTrb->TC    = 1;
494   //
495   // Set Cycle bit as other TRB PCS init value
496   //
497   EndTrb->CycleBit = 0;
498 }
499 
500 /**
501   Create debug capability context for XHC debug device.
502 
503   @param  Handle       Debug port handle.
504 
505   @retval EFI_SUCCESS  The bit successfully changed by host controller.
506   @retval EFI_TIMEOUT  The time out occurred.
507 
508 **/
509 EFI_STATUS
CreateDebugCapabilityContext(IN USB3_DEBUG_PORT_HANDLE * Handle)510 CreateDebugCapabilityContext (
511   IN  USB3_DEBUG_PORT_HANDLE   *Handle
512   )
513 {
514   VOID                        *Buf;
515   XHC_DC_CONTEXT              *DebugCapabilityContext;
516   UINT8                       *String0Desc;
517   UINT8                       *ManufacturerStrDesc;
518   UINT8                       *ProductStrDesc;
519   UINT8                       *SerialNumberStrDesc;
520 
521   //
522   // Allocate debug device context
523   //
524   Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));
525   ASSERT (Buf != NULL);
526   ASSERT (((UINTN) Buf & 0xF) == 0);
527   ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));
528 
529   DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN) Buf;
530   Handle->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN) DebugCapabilityContext;
531 
532   //
533   // Initialize DbcInfoContext.
534   //
535   DebugCapabilityContext->DbcInfoContext.String0Length         = STRING0_DESC_LEN;
536   DebugCapabilityContext->DbcInfoContext.ManufacturerStrLength = MANU_DESC_LEN;
537   DebugCapabilityContext->DbcInfoContext.ProductStrLength      = PRODUCT_DESC_LEN;
538   DebugCapabilityContext->DbcInfoContext.SerialNumberStrLength = SERIAL_DESC_LEN;
539 
540   //
541   // Initialize EpOutContext.
542   //
543   DebugCapabilityContext->EpOutContext.CErr             = 0x3;
544   DebugCapabilityContext->EpOutContext.EPType           = ED_BULK_OUT;
545   DebugCapabilityContext->EpOutContext.MaxPacketSize    = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
546   DebugCapabilityContext->EpOutContext.AverageTRBLength = 0x1000;
547 
548   //
549   // Initialize EpInContext.
550   //
551   DebugCapabilityContext->EpInContext.CErr             = 0x3;
552   DebugCapabilityContext->EpInContext.EPType           = ED_BULK_IN;
553   DebugCapabilityContext->EpInContext.MaxPacketSize    = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
554   DebugCapabilityContext->EpInContext.AverageTRBLength = 0x1000;
555 
556   //
557   // Update string descriptor address
558   //
559   String0Desc = (UINT8 *) AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
560   ASSERT (String0Desc != NULL);
561   ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
562   CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);
563   DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;
564 
565   ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;
566   CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);
567   DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;
568 
569   ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;
570   CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);
571   DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;
572 
573   SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;
574   CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);
575   DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;
576 
577   //
578   // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
579   //
580   ZeroMem (&Handle->TransferRingIn, sizeof (TRANSFER_RING));
581   CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingIn);
582   DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingIn.RingSeg0) | BIT0;
583   DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingIn.RingSeg0);
584 
585   //
586   // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
587   //
588   ZeroMem (&Handle->TransferRingOut, sizeof (TRANSFER_RING));
589   CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingOut);
590   DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingOut.RingSeg0) | BIT0;
591   DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingOut.RingSeg0);
592 
593   //
594   // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
595   //
596   XhcWriteDebugReg (
597     Handle,
598     XHC_DC_DCCP,
599     XHC_LOW_32BIT((UINT64)(UINTN)DebugCapabilityContext)
600     );
601   XhcWriteDebugReg (
602     Handle,
603     XHC_DC_DCCP + 4,
604     XHC_HIGH_32BIT((UINT64)(UINTN)DebugCapabilityContext)
605     );
606   return EFI_SUCCESS;
607 }
608 
609 /**
610   Check if debug device is running.
611 
612   @param  Handle       Debug port handle.
613 
614 **/
615 VOID
XhcDetectDebugCapabilityReady(IN USB3_DEBUG_PORT_HANDLE * Handle)616 XhcDetectDebugCapabilityReady (
617   IN USB3_DEBUG_PORT_HANDLE *Handle
618   )
619 {
620   UINT64                          TimeOut;
621   volatile UINT32                 Dcctrl;
622 
623   TimeOut = 1;
624   if (Handle->Initialized == USB3DBG_DBG_CAB) {
625     //
626     // As detection is slow in seconds, wait for longer timeout for the first time.
627     // If first initialization is failed, we will try to enable debug device in the
628     // Poll function invoked by timer.
629     //
630     TimeOut = DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout), XHC_POLL_DELAY) + 1;
631   }
632 
633   do {
634     //
635     // Check if debug device is in configured state
636     //
637     Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
638     if ((Dcctrl & BIT0) != 0) {
639       //
640       // Set the flag to indicate debug device is in configured state
641       //
642       Handle->Ready = TRUE;
643       break;
644     }
645     MicroSecondDelay (XHC_POLL_DELAY);
646     TimeOut--;
647   } while (TimeOut != 0);
648 }
649 
650 /**
651   Initialize usb debug port hardware.
652 
653   @param  Handle           Debug port handle.
654 
655   @retval TRUE             The usb debug port hardware configuration is changed.
656   @retval FALSE            The usb debug port hardware configuration is not changed.
657 
658 **/
659 RETURN_STATUS
660 EFIAPI
InitializeUsbDebugHardware(IN USB3_DEBUG_PORT_HANDLE * Handle)661 InitializeUsbDebugHardware (
662   IN USB3_DEBUG_PORT_HANDLE *Handle
663   )
664 {
665   RETURN_STATUS                   Status;
666   UINT8                           *Buffer;
667   UINTN                           Index;
668   UINT8                           TotalUsb3Port;
669   EFI_PHYSICAL_ADDRESS            XhciOpRegister;
670   UINT32                          Dcddi1;
671 
672   XhciOpRegister = Handle->XhciOpRegister;
673   TotalUsb3Port = MmioRead32 (((UINTN) Handle->XhciMmioBase + XHC_HCSPARAMS1_OFFSET)) >> 24;
674 
675   if (Handle->Initialized == USB3DBG_NOT_ENABLED) {
676     Dcddi1 = XhcReadDebugReg (Handle,XHC_DC_DCDDI1);
677     if (Dcddi1 != (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)) {
678       //
679       // The debug capability has been reset by other code, return device error.
680       //
681       return EFI_DEVICE_ERROR;
682     }
683     //
684     // If XHCI supports debug capability, hardware resource has been allocated,
685     // but it has not been enabled, try to enable again.
686     //
687     goto Enable;
688   }
689 
690   //
691   // Initialize for PEI phase when AllocatePages can work.
692   // Allocate data buffer with max packet size for data read and data poll.
693   // Allocate data buffer for data write.
694   //
695   Buffer = AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE);
696   if (Buffer == NULL) {
697     //
698     // AllocatePages can not still work now, return fail and do not initialize now.
699     //
700     return RETURN_NOT_READY;
701   }
702 
703   //
704   // Reset port to get debug device discovered
705   //
706   for (Index = 0; Index < TotalUsb3Port; Index++) {
707     XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT4);
708     MicroSecondDelay (10 * 1000);
709   }
710 
711   //
712   // Clear DCE bit and LSE bit in DCCTRL
713   //
714   if ((XhcReadDebugReg (Handle, XHC_DC_DCCTRL) & (BIT1|BIT31)) == (BIT1|BIT31)) {
715     XhcClearDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
716   }
717 
718   //
719   // Construct the buffer for read, poll and write.
720   //
721   Handle->UrbIn.Data  = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer;
722   Handle->Data        = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
723   Handle->UrbOut.Data = Handle->UrbIn.Data + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2;
724 
725   //
726   // Initialize event ring
727   //
728   ZeroMem (&Handle->EventRing, sizeof (EVENT_RING));
729   Status = CreateEventRing (Handle, &Handle->EventRing);
730   ASSERT_EFI_ERROR (Status);
731 
732   //
733   // Init IN and OUT endpoint context
734   //
735   Status = CreateDebugCapabilityContext (Handle);
736   ASSERT_EFI_ERROR (Status);
737 
738   //
739   // Init DCDDI1 and DCDDI2
740   //
741   XhcWriteDebugReg (
742    Handle,
743    XHC_DC_DCDDI1,
744    (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
745    );
746 
747   XhcWriteDebugReg (
748    Handle,
749    XHC_DC_DCDDI2,
750    (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
751    );
752 
753 Enable:
754   if ((Handle->Initialized == USB3DBG_NOT_ENABLED) && (!Handle->ChangePortPower)) {
755     //
756     // If the first time detection is failed, turn port power off and on in order to
757     // reset port status this time, then try to check if debug device is ready again.
758     //
759     for (Index = 0; Index < TotalUsb3Port; Index++) {
760       XhcClearR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
761       MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
762       XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
763       MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
764       Handle->ChangePortPower = TRUE;
765     }
766   }
767 
768   //
769   // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization
770   //
771   XhcSetDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
772 
773   XhcDetectDebugCapabilityReady (Handle);
774 
775   Status = RETURN_SUCCESS;
776   if (!Handle->Ready) {
777     Handle->Initialized = USB3DBG_NOT_ENABLED;
778     Status = RETURN_NOT_READY;
779   } else {
780     Handle->Initialized = USB3DBG_ENABLED;
781   }
782 
783   return Status;
784 }
785 
786 /**
787   Discover and initialize usb debug port.
788 
789   @param Handle                 Debug port handle.
790 
791 **/
792 VOID
DiscoverInitializeUsbDebugPort(IN USB3_DEBUG_PORT_HANDLE * Handle)793 DiscoverInitializeUsbDebugPort (
794   IN USB3_DEBUG_PORT_HANDLE     *Handle
795   )
796 {
797   EFI_STATUS                    Status;
798   EFI_PHYSICAL_ADDRESS          XhciMmioBase;
799 
800   //
801   // Read 64-bit MMIO base address
802   //
803   XhciMmioBase = ProgramXhciBaseAddress ();
804   Handle->XhciMmioBase = XhciMmioBase;
805 
806   Status = CalculateUsbDebugPortMmioBase (Handle);
807   if (!RETURN_ERROR (Status)) {
808     UpdateXhcResource (Handle, XhciMmioBase);
809     if (NeedReinitializeHardware (Handle)) {
810       InitializeUsbDebugHardware (Handle);
811     }
812   }
813 }
814 
815 /**
816   Set USB3 debug instance address.
817 
818   @param[in] Instance           Debug port instance.
819 
820 **/
821 VOID
SetUsb3DebugPortInstance(IN USB3_DEBUG_PORT_HANDLE * Instance)822 SetUsb3DebugPortInstance (
823   IN USB3_DEBUG_PORT_HANDLE     *Instance
824   )
825 {
826   EFI_PHYSICAL_ADDRESS          *AddrPtr;
827 
828   AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();
829   ASSERT (AddrPtr != NULL);
830   *AddrPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) Instance;
831 }
832 
833 /**
834   Return USB3 debug instance address.
835 
836 **/
837 USB3_DEBUG_PORT_HANDLE *
GetUsb3DebugPortInstance(VOID)838 GetUsb3DebugPortInstance (
839   VOID
840   )
841 {
842   EFI_PHYSICAL_ADDRESS          *AddrPtr;
843   USB3_DEBUG_PORT_HANDLE        *Instance;
844 
845   AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();
846   ASSERT (AddrPtr != NULL);
847 
848   Instance = (USB3_DEBUG_PORT_HANDLE *) (UINTN) *AddrPtr;
849 
850   return Instance;
851 }
852 
853 /**
854   Read data from debug device and save the data in buffer.
855 
856   Reads NumberOfBytes data bytes from a debug device into the buffer
857   specified by Buffer. The number of bytes actually read is returned.
858   If the return value is less than NumberOfBytes, then the rest operation failed.
859   If NumberOfBytes is zero, then return 0.
860 
861   @param  Handle           Debug port handle.
862   @param  Buffer           Pointer to the data buffer to store the data read from the debug device.
863   @param  NumberOfBytes    Number of bytes which will be read.
864   @param  Timeout          Timeout value for reading from debug device. Its unit is Microsecond.
865 
866   @retval 0                Read data failed, no data is to be read.
867   @retval >0               Actual number of bytes read from debug device.
868 
869 **/
870 UINTN
871 EFIAPI
DebugPortReadBuffer(IN DEBUG_PORT_HANDLE Handle,IN UINT8 * Buffer,IN UINTN NumberOfBytes,IN UINTN Timeout)872 DebugPortReadBuffer (
873   IN   DEBUG_PORT_HANDLE        Handle,
874   IN   UINT8                    *Buffer,
875   IN   UINTN                    NumberOfBytes,
876   IN   UINTN                    Timeout
877   )
878 {
879   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;
880   UINT8                     Index;
881   UINT8                     *Data;
882 
883   if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
884     return 0;
885   }
886 
887   //
888   // If Handle is NULL, get own instance.
889   // If Handle is not NULL, use it and set the instance.
890   //
891   if (Handle != NULL) {
892     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;
893     SetUsb3DebugPortInstance (UsbDebugPortHandle);
894   } else {
895     UsbDebugPortHandle = GetUsb3DebugPortInstance ();
896   }
897   if (UsbDebugPortHandle == NULL) {
898     return 0;
899   }
900 
901   if (UsbDebugPortHandle->InNotify) {
902     return 0;
903   }
904 
905   DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
906 
907   if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
908     return 0;
909   }
910 
911   Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;
912 
913   //
914   // Read data from buffer
915   //
916   if (UsbDebugPortHandle->DataCount < 1) {
917     return 0;
918   } else {
919     *Buffer = Data[0];
920 
921     for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
922       if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
923         return 0;
924       }
925       Data[Index] = Data[Index + 1];
926     }
927     UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
928     return 1;
929   }
930 }
931 
932 /**
933   Write data from buffer to debug device.
934 
935   Writes NumberOfBytes data bytes from Buffer to the debug device.
936   The number of bytes actually written to the debug device is returned.
937   If the return value is less than NumberOfBytes, then the write operation failed.
938   If NumberOfBytes is zero, then return 0.
939 
940   @param  Handle           Debug port handle.
941   @param  Buffer           Pointer to the data buffer to be written.
942   @param  NumberOfBytes    Number of bytes to written to the debug device.
943 
944   @retval 0                NumberOfBytes is 0.
945   @retval >0               The number of bytes written to the debug device.
946                            If this value is less than NumberOfBytes, then the write operation failed.
947 
948 **/
949 UINTN
950 EFIAPI
DebugPortWriteBuffer(IN DEBUG_PORT_HANDLE Handle,IN UINT8 * Buffer,IN UINTN NumberOfBytes)951 DebugPortWriteBuffer (
952   IN   DEBUG_PORT_HANDLE    Handle,
953   IN   UINT8                *Buffer,
954   IN   UINTN                NumberOfBytes
955   )
956 {
957   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;
958   UINTN                     Sent;
959   UINTN                     Total;
960 
961   if (NumberOfBytes == 0 || Buffer == NULL) {
962     return 0;
963   }
964 
965   Sent  = 0;
966   Total = 0;
967 
968   //
969   // If Handle is NULL, get own instance.
970   // If Handle is not NULL, use it and set the instance.
971   //
972   if (Handle != NULL) {
973     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;
974     SetUsb3DebugPortInstance (UsbDebugPortHandle);
975   } else {
976     UsbDebugPortHandle = GetUsb3DebugPortInstance ();
977   }
978   if (UsbDebugPortHandle == NULL) {
979     return 0;
980   }
981 
982   if (UsbDebugPortHandle->InNotify) {
983     return 0;
984   }
985 
986   DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
987 
988   if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
989     return 0;
990   }
991 
992   //
993   // When host is trying to send data, write will be blocked.
994   // Poll to see if there is any data sent by host at first.
995   //
996   DebugPortPollBuffer (UsbDebugPortHandle);
997 
998   while ((Total < NumberOfBytes)) {
999     if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {
1000       Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;
1001     } else {
1002       Sent = (UINT8)(NumberOfBytes - Total);
1003     }
1004     XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);
1005     Total += Sent;
1006   }
1007 
1008   return Total;
1009 }
1010 
1011 /**
1012   Polls a debug device to see if there is any data waiting to be read.
1013 
1014   Polls a debug device to see if there is any data waiting to be read.
1015   If there is data waiting to be read from the debug device, then TRUE is returned.
1016   If there is no data waiting to be read from the debug device, then FALSE is returned.
1017 
1018   @param  Handle           Debug port handle.
1019 
1020   @retval TRUE             Data is waiting to be read from the debug device.
1021   @retval FALSE            There is no data waiting to be read from the debug device.
1022 
1023 **/
1024 BOOLEAN
1025 EFIAPI
DebugPortPollBuffer(IN DEBUG_PORT_HANDLE Handle)1026 DebugPortPollBuffer (
1027   IN DEBUG_PORT_HANDLE      Handle
1028   )
1029 {
1030   USB3_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
1031   UINTN                     Length;
1032 
1033   //
1034   // If Handle is NULL, get own instance.
1035   // If Handle is not NULL, use it and set the instance.
1036   //
1037   if (Handle != NULL) {
1038     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;
1039     SetUsb3DebugPortInstance (UsbDebugPortHandle);
1040   } else {
1041     UsbDebugPortHandle = GetUsb3DebugPortInstance ();
1042   }
1043   if (UsbDebugPortHandle == NULL) {
1044     return FALSE;
1045   }
1046 
1047   if (UsbDebugPortHandle->InNotify) {
1048     return FALSE;
1049   }
1050 
1051   DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
1052 
1053   if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
1054     return FALSE;
1055   }
1056 
1057   //
1058   // If the data buffer is not empty, then return TRUE directly.
1059   // Otherwise initialize a usb read transaction and read data to internal data buffer.
1060   //
1061   if (UsbDebugPortHandle->DataCount != 0) {
1062     return TRUE;
1063   }
1064 
1065   //
1066   // Read data as much as we can
1067   //
1068   Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
1069   XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);
1070 
1071   if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
1072     return FALSE;
1073   }
1074 
1075   if (Length == 0) {
1076     return FALSE;
1077   }
1078 
1079   //
1080   // Store data into internal buffer for use later
1081   //
1082   UsbDebugPortHandle->DataCount = (UINT8) Length;
1083   return TRUE;
1084 }
1085 
1086 /**
1087   Initialize the debug port.
1088 
1089   If Function is not NULL, Debug Communication Library will call this function
1090   by passing in the Context to be the first parameter. If needed, Debug Communication
1091   Library will create one debug port handle to be the second argument passing in
1092   calling the Function, otherwise it will pass NULL to be the second argument of
1093   Function.
1094 
1095   If Function is NULL, and Context is not NULL, the Debug Communication Library could
1096     a) Return the same handle as passed in (as Context parameter).
1097     b) Ignore the input Context parameter and create new handle to be returned.
1098 
1099   If parameter Function is NULL and Context is NULL, Debug Communication Library could
1100   created a new handle if needed and return it, otherwise it will return NULL.
1101 
1102   @param[in] Context      Context needed by callback function; it was optional.
1103   @param[in] Function     Continue function called by Debug Communication library;
1104                           it was optional.
1105 
1106   @return  The debug port handle created by Debug Communication Library if Function
1107            is not NULL.
1108 
1109 **/
1110 DEBUG_PORT_HANDLE
1111 EFIAPI
DebugPortInitialize(IN VOID * Context,IN DEBUG_PORT_CONTINUE Function)1112 DebugPortInitialize (
1113   IN VOID                 *Context,
1114   IN DEBUG_PORT_CONTINUE  Function
1115   )
1116 {
1117   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;
1118 
1119   //
1120   // Validate the PCD PcdDebugPortHandleBufferSize value
1121   //
1122   ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));
1123 
1124   if (Function == NULL && Context != NULL) {
1125     SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE *) Context);
1126     return (DEBUG_PORT_HANDLE) Context;
1127   }
1128   UsbDebugPortHandle = GetUsb3DebugPortInstance ();
1129   if (UsbDebugPortHandle == NULL) {
1130     return NULL;
1131   }
1132 
1133   DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
1134 
1135   if (Function != NULL) {
1136     Function (Context, (DEBUG_PORT_HANDLE) UsbDebugPortHandle);
1137   }
1138 
1139   return (DEBUG_PORT_HANDLE) UsbDebugPortHandle;
1140 }
1141