• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Debug Port Library implementation based on usb debug port.
3 
4   Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php.
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <Base.h>
16 #include <IndustryStandard/Pci.h>
17 #include <IndustryStandard/Usb.h>
18 #include <Library/IoLib.h>
19 #include <Library/PciLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/TimerLib.h>
22 #include <Library/DebugCommunicationLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/BaseLib.h>
25 #include <Library/DebugLib.h>
26 
27 #define SETUP_PID            0x2D
28 #define INPUT_PID            0x69
29 #define OUTPUT_PID           0xE1
30 #define ERROR_PID            0x55
31 #define DATA0_PID            0xC3
32 #define DATA1_PID            0x4B
33 #define DATA2_PID            0x87
34 #define MDATA_PID            0x0F
35 #define ACK_PID              0xD2
36 #define NAK_PID              0x5A
37 #define STALL_PID            0x1E
38 #define NYET_PID             0x96
39 
40 #define PCI_CAPABILITY_ID_DEBUG_PORT   0x0A
41 #define USB_DEBUG_PORT_MAX_PACKET_SIZE 0x08
42 
43 #define USB_DEBUG_PORT_IN_USE     BIT10
44 #define USB_DEBUG_PORT_ENABLE     BIT28
45 #define USB_DEBUG_PORT_OWNER      BIT30
46 
47 #define USB_PORT_LINE_STATUS_LS   0x400
48 #define USB_PORT_LINE_STATUS_MASK 0xC00
49 
50 //
51 // Usb debug device descriptor, which is defined at
52 // USB2 Debug Device Specification.
53 //
54 typedef struct _USB_DEBUG_PORT_DESCRIPTOR {
55   UINT8          Length;
56   UINT8          DescriptorType;
57   UINT8          DebugInEndpoint;
58   UINT8          DebugOutEndpoint;
59 }USB_DEBUG_PORT_DESCRIPTOR;
60 
61 USB_DEVICE_REQUEST mDebugCommunicationLibUsbGetDebugDescriptor = {
62   0x80,
63   USB_REQ_GET_DESCRIPTOR,
64   (UINT16)(0x0A << 8),
65   0x0000,
66   sizeof(USB_DEBUG_PORT_DESCRIPTOR)
67   };
68 
69 USB_DEVICE_REQUEST mDebugCommunicationLibUsbSetDebugFeature = {
70   0x0,
71   USB_REQ_SET_FEATURE,
72   (UINT16)(0x06),
73   0x0000,
74   0x0
75   };
76 
77 USB_DEVICE_REQUEST mDebugCommunicationLibUsbSetDebugAddress = {
78   0x0,
79   USB_REQ_SET_ADDRESS,
80   (UINT16)(0x7F),
81   0x0000,
82   0x0
83   };
84 
85 //
86 // Usb debug port register file, which is defined at
87 // EHCI Specification.
88 //
89 typedef struct _USB_DEBUG_PORT_REGISTER {
90   UINT32         ControlStatus;
91   UINT8          TokenPid;
92   UINT8          SendPid;
93   UINT8          ReceivedPid;
94   UINT8          Reserved1;
95   UINT8          DataBuffer[8];
96   UINT8          UsbEndPoint;
97   UINT8          UsbAddress;
98   UINT8          Reserved2;
99   UINT8          Reserved3;
100 }USB_DEBUG_PORT_REGISTER;
101 
102 //
103 // The state machine of usb debug port
104 //
105 #define USBDBG_NO_DEV        0   // No device present at debug port
106 #define USBDBG_NO_DBG_CAB    1   // The device attached is not usb debug cable
107 #define USBDBG_DBG_CAB       2   // The device attached is usb debug cable
108 #define USBDBG_INIT_DONE     4   // The usb debug cable device is initialized
109 #define USBDBG_RESET         8   // The system is reset
110 
111 #pragma pack(1)
112 //
113 // The internal data structure of DEBUG_PORT_HANDLE, which stores some
114 // important datum which are used across various phases.
115 //
116 typedef struct _USB_DEBUG_PORT_HANDLE{
117   //
118   // The usb debug port memory BAR number in EHCI configuration space.
119   //
120   UINT8        DebugPortBarNumber;
121   UINT8        Initialized;
122   //
123   // The offset of usb debug port registers in EHCI memory range.
124   //
125   UINT16       DebugPortOffset;
126   //
127   // The usb debug port memory BAR address.
128   //
129   UINT32       UsbDebugPortMemoryBase;
130   //
131   // The EHCI memory BAR address.
132   //
133   UINT32       EhciMemoryBase;
134   //
135   // The Bulk In endpoint toggle bit.
136   //
137   UINT8        BulkInToggle;
138   //
139   // The Bulk Out endpoint toggle bit.
140   //
141   UINT8        BulkOutToggle;
142   //
143   // The available data length in the following data buffer.
144   //
145   UINT8        DataCount;
146   //
147   // The data buffer. Maximum length is 8 bytes.
148   //
149   UINT8        Data[8];
150 } USB_DEBUG_PORT_HANDLE;
151 #pragma pack()
152 
153 //
154 // The global variable which can be used after memory is ready.
155 //
156 USB_DEBUG_PORT_HANDLE     mDebugCommunicationLibUsbDebugPortHandle;
157 
158 /**
159   Calculate the usb debug port bar address.
160 
161   @param  DebugPortOffset    Get usb debug port offset in the usb debug port memory space.
162   @param  DebugPortBarNumbar Get the bar number at which usb debug port is located.
163 
164   @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.
165   @retval RETURN_SUCCESS     Get bar and offset successfully.
166 
167 **/
168 RETURN_STATUS
169 EFIAPI
CalculateUsbDebugPortBar(OUT UINT16 * DebugPortOffset,OUT UINT8 * DebugPortBarNumbar)170 CalculateUsbDebugPortBar (
171   OUT UINT16     *DebugPortOffset,
172   OUT UINT8      *DebugPortBarNumbar
173  )
174 {
175   UINT16     PciStatus;
176   UINT16     VendorId;
177   UINT16     DeviceId;
178   UINT8      ProgInterface;
179   UINT8      SubClassCode;
180   UINT8      BaseCode;
181   UINT8      CapabilityPtr;
182   UINT8      CapabilityId;
183 
184   VendorId = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_VENDOR_ID_OFFSET);
185   DeviceId = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_DEVICE_ID_OFFSET);
186 
187   if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {
188     return RETURN_UNSUPPORTED;
189   }
190 
191   ProgInterface = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET);
192   SubClassCode  = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET + 1);
193   BaseCode      = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET + 2);
194 
195   if ((ProgInterface != PCI_IF_EHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {
196     return RETURN_UNSUPPORTED;
197   }
198 
199   //
200   // Enable Ehci Host Controller MMIO Space.
201   //
202   PciStatus = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_PRIMARY_STATUS_OFFSET);
203 
204   if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
205     //
206     // The Pci Device Doesn't Support Capability Pointer.
207     //
208     return RETURN_UNSUPPORTED;
209   }
210 
211   //
212   // Get Pointer To Capability List
213   //
214   CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + PCI_CAPBILITY_POINTER_OFFSET);
215 
216   //
217   // Find Capability ID 0xA, Which Is For Debug Port
218   //
219   while (CapabilityPtr != 0) {
220     CapabilityId = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr);
221     if (CapabilityId == PCI_CAPABILITY_ID_DEBUG_PORT) {
222       break;
223     }
224     CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 1);
225   }
226 
227   //
228   // No Debug Port Capability Found
229   //
230   if (CapabilityPtr == 0) {
231     return RETURN_UNSUPPORTED;
232   }
233 
234   //
235   // Get The Base Address Of Debug Port Register In Debug Port Capability Register
236   //
237   *DebugPortOffset    = (UINT16)(PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) & 0x1FFF);
238   *DebugPortBarNumbar = (UINT8)((PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) >> 13) - 1);
239 
240   return RETURN_SUCCESS;
241 }
242 
243 /**
244   Do a usb IN transaction by usb debug port.
245 
246   @param  DebugPortRegister        Pointer to the base address of usb debug port register interface.
247   @param  Buffer                   Pointer to the buffer receiving data.
248   @param  Length                   Number of bytes of the received data.
249   @param  Token                    The token PID for each USB transaction.
250   @param  Addr                     The usb device address for usb transaction.
251   @param  Ep                       The endpoint for usb transaction.
252   @param  DataToggle               The toggle bit used at usb transaction.
253 
254   @retval RETURN_SUCCESS           The IN transaction is executed successfully.
255   @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
256   @retval RETURN_DEVICE_ERROR      The IN transaction comes across error.
257 
258 **/
259 RETURN_STATUS
260 EFIAPI
UsbDebugPortIn(IN USB_DEBUG_PORT_REGISTER * DebugPortRegister,IN OUT UINT8 * Buffer,OUT UINT8 * Length,IN UINT8 Token,IN UINT8 Addr,IN UINT8 Ep,IN UINT8 DataToggle)261 UsbDebugPortIn (
262   IN      USB_DEBUG_PORT_REGISTER         *DebugPortRegister,
263   IN  OUT UINT8                           *Buffer,
264       OUT UINT8                           *Length,
265   IN      UINT8                           Token,
266   IN      UINT8                           Addr,
267   IN      UINT8                           Ep,
268   IN      UINT8                           DataToggle
269   )
270 {
271   UINTN                   Index;
272 
273   if (Length == NULL) {
274     return RETURN_INVALID_PARAMETER;
275   }
276   *Length = 0;
277 
278   DebugPortRegister->TokenPid = Token;
279   if (DataToggle != 0) {
280     DebugPortRegister->SendPid = DATA1_PID;
281   } else {
282     DebugPortRegister->SendPid = DATA0_PID;
283   }
284 
285   DebugPortRegister->UsbAddress  = (UINT8)(Addr & 0x7F);
286   DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);
287 
288   //
289   // Clearing W/R bit to indicate it's a READ operation
290   //
291   MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~BIT4);
292 
293   //
294   // Setting GO bit as well as clearing DONE bit
295   //
296   MmioOr32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)BIT5);
297 
298   //
299   // Wait for completing the request
300   //
301   while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {
302     if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))
303        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {
304       return RETURN_DEVICE_ERROR;
305     }
306   }
307 
308   //
309   // Clearing DONE bit by writing 1
310   //
311   MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT16);
312 
313   //
314   // Check if the request is executed successfully or not.
315   //
316   if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {
317     return RETURN_DEVICE_ERROR;
318   }
319 
320   //
321   // Make sure the received data are not beyond the allowable maximum length - 8 byte
322   //
323   if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
324     return RETURN_DEVICE_ERROR;
325   }
326 
327   *Length = (UINT8)(MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & 0xF);
328   if (*Length > 8) {
329     return RETURN_DEVICE_ERROR;
330   }
331 
332   for (Index = 0; Index < *Length; Index++) {
333     Buffer[Index] = DebugPortRegister->DataBuffer[Index];
334   }
335   return RETURN_SUCCESS;
336 }
337 
338 /**
339   Do a usb SETUP/OUT transaction by usb debug port.
340 
341   @param  DebugPortRegister        Pointer to the base address of usb debug port register interface.
342   @param  Buffer                   Pointer to the buffer receiving data.
343   @param  Length                   Number of bytes of the received data.
344   @param  Token                    The token PID for each USB transaction.
345   @param  Addr                     The usb device address for usb transaction.
346   @param  Ep                       The endpoint for usb transaction.
347   @param  DataToggle               The toggle bit used at usb transaction.
348 
349   @retval RETURN_SUCCESS           The IN transaction is executed successfully.
350   @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
351   @retval RETURN_DEVICE_ERROR      The IN transaction comes across error.
352 
353 **/
354 RETURN_STATUS
355 EFIAPI
UsbDebugPortOut(IN USB_DEBUG_PORT_REGISTER * DebugPortRegister,IN UINT8 * Buffer,IN UINT8 Length,IN UINT8 Token,IN UINT8 Addr,IN UINT8 Ep,IN UINT8 DataToggle)356 UsbDebugPortOut (
357   IN  USB_DEBUG_PORT_REGISTER         *DebugPortRegister,
358   IN  UINT8                           *Buffer,
359   IN  UINT8                           Length,
360   IN  UINT8                           Token,
361   IN  UINT8                           Addr,
362   IN  UINT8                           Ep,
363   IN  UINT8                           DataToggle
364   )
365 {
366   UINT8             Index;
367 
368   if (Length > 8) {
369     return RETURN_INVALID_PARAMETER;
370   }
371 
372   DebugPortRegister->TokenPid = Token;
373   if (DataToggle != 0) {
374     DebugPortRegister->SendPid = DATA1_PID;
375   } else {
376     DebugPortRegister->SendPid = DATA0_PID;
377   }
378   DebugPortRegister->UsbAddress  = (UINT8)(Addr & 0x7F);
379   DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);
380 
381   //
382   // Fill in the data length and corresponding data.
383   //
384   MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~0xF);
385   MmioOr32((UINTN)&DebugPortRegister->ControlStatus, Length & 0xF);
386   for (Index = 0; Index < Length; Index++) {
387     DebugPortRegister->DataBuffer[Index] = Buffer[Index];
388   }
389 
390   //
391   // Setting W/R bit to indicate it's a WRITE operation
392   //
393   MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT4);
394   //
395   // Setting GO bit as well as clearing DONE bit
396   //
397   MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT5);
398 
399   //
400   // Wait for completing the request
401   //
402   while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0) {
403     if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))
404        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {
405       return RETURN_DEVICE_ERROR;
406     }
407   }
408 
409   //
410   // Clearing DONE bit by writing 1
411   //
412   MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT16);
413 
414   //
415   // Check if the request is executed successfully or not.
416   //
417   if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {
418     return RETURN_DEVICE_ERROR;
419   }
420 
421   //
422   // Make sure the sent data are not beyond the allowable maximum length - 8 byte
423   //
424   if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
425     return RETURN_DEVICE_ERROR;
426   }
427 
428   return RETURN_SUCCESS;
429 }
430 
431 /**
432   Do a usb control transfer by usb debug port.
433 
434   @param  DebugPortRegister        Pointer to the base address of usb debug port register interface.
435   @param  SetupPacket              The token PID for each USB transaction.
436   @param  Addr                     The usb device address for usb transaction.
437   @param  Ep                       The endpoint for usb transaction.
438   @param  Data                     Pointer to the buffer receiving data.
439   @param  DataLength               Number of bytes of the received data.
440 
441   @retval RETURN_SUCCESS           The IN transaction is executed successfully.
442   @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
443   @retval RETURN_DEVICE_ERROR      The IN transaction comes across error.
444 
445 **/
446 RETURN_STATUS
447 EFIAPI
UsbDebugPortControlTransfer(IN USB_DEBUG_PORT_REGISTER * DebugPortRegister,IN USB_DEVICE_REQUEST * SetupPacket,IN UINT8 Addr,IN UINT8 Ep,OUT UINT8 * Data,IN OUT UINT8 * DataLength)448 UsbDebugPortControlTransfer (
449   IN      USB_DEBUG_PORT_REGISTER         *DebugPortRegister,
450   IN      USB_DEVICE_REQUEST              *SetupPacket,
451   IN      UINT8                           Addr,
452   IN      UINT8                           Ep,
453       OUT UINT8                           *Data,
454   IN  OUT UINT8                           *DataLength
455   )
456 {
457   RETURN_STATUS          Status;
458   UINT8                  Temp;
459   UINT8                  ReturnStatus[8];
460 
461   //
462   // Setup Phase
463   //
464   Status = UsbDebugPortOut(DebugPortRegister, (UINT8 *)SetupPacket, (UINT8)sizeof(USB_DEVICE_REQUEST), SETUP_PID, Addr, Ep, 0);
465   if (RETURN_ERROR(Status)) {
466     return Status;
467   }
468 
469   //
470   // Data Phase
471   //
472   if (DataLength != 0) {
473     if ((SetupPacket->RequestType & BIT7) != 0) {
474       //
475       // Get Data From Device
476       //
477       Status = UsbDebugPortIn(DebugPortRegister, Data, DataLength, INPUT_PID, Addr, Ep, 1);
478       if (RETURN_ERROR(Status)) {
479         return Status;
480       }
481     } else {
482       //
483       // Send Data To Device
484       //
485       Status = UsbDebugPortOut(DebugPortRegister, Data, *DataLength, OUTPUT_PID, Addr, Ep, 1);
486       if (RETURN_ERROR(Status)) {
487         return Status;
488       }
489     }
490   }
491 
492   //
493   // Status Phase
494   //
495   if ((SetupPacket->RequestType & BIT7) != 0) {
496     //
497     // For READ operation, Data Toggle in Status Phase Should be 1.
498     //
499     Status = UsbDebugPortOut(DebugPortRegister, NULL, 0, OUTPUT_PID, Addr, Ep, 1);
500   } else {
501     //
502     // For WRITE operation, Data Toggle in Status Phase Should be 1.
503     //
504     Status = UsbDebugPortIn(DebugPortRegister, ReturnStatus, &Temp, INPUT_PID, Addr, Ep, 1);
505   }
506 
507   return Status;
508 }
509 
510 /**
511   Check if it needs to re-initialize usb debug port hardware.
512 
513   During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
514   whether the usb debug port hardware configuration is changed. Such case can be triggered by
515   Pci bus resource allocation and so on.
516 
517   @param  Handle           Debug port handle.
518 
519   @retval TRUE             The usb debug port hardware configuration is changed.
520   @retval FALSE            The usb debug port hardware configuration is not changed.
521 
522 **/
523 BOOLEAN
524 EFIAPI
NeedReinitializeHardware(IN USB_DEBUG_PORT_HANDLE * Handle)525 NeedReinitializeHardware(
526   IN USB_DEBUG_PORT_HANDLE *Handle
527   )
528 {
529   UINT16                  PciCmd;
530   UINT32                  UsbDebugPortMemoryBase;
531   UINT32                  EhciMemoryBase;
532   BOOLEAN                 Status;
533   USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;
534 
535   Status = FALSE;
536 
537   EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
538   if (EhciMemoryBase != Handle->EhciMemoryBase) {
539     Handle->EhciMemoryBase = EhciMemoryBase;
540     Status = TRUE;
541   }
542 
543   UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle->DebugPortBarNumber * 4);
544   if (UsbDebugPortMemoryBase != Handle->UsbDebugPortMemoryBase) {
545     Handle->UsbDebugPortMemoryBase = UsbDebugPortMemoryBase;
546     Status = TRUE;
547   }
548 
549   //
550   // Enable Ehci Memory Space Access
551   //
552   PciCmd    = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);
553   if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
554     PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;
555     PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);
556     Status = TRUE;
557   }
558 
559   //
560   // If the owner and in_use bit is not set, it means system is doing cold/warm boot or EHCI host controller is reset by system software.
561   //
562   UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);
563   if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE))
564        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) {
565     Status = TRUE;
566   }
567 
568   if (Handle->Initialized == USBDBG_RESET) {
569     Status = TRUE;
570   } else if (Handle->Initialized != USBDBG_INIT_DONE) {
571     Status = TRUE;
572   }
573   return Status;
574 }
575 
576 /**
577   Initialize usb debug port hardware.
578 
579   1. reset ehci host controller.
580   2. set right port to debug port.
581   3. find a usb debug device is attached by getting debug device descriptor.
582   4. set address for the usb debug device.
583   5. configure the usb debug device to debug mode.
584 
585   @param  Handle           Debug port handle.
586 
587   @retval TRUE             The usb debug port hardware configuration is changed.
588   @retval FALSE            The usb debug port hardware configuration is not changed.
589 
590 **/
591 RETURN_STATUS
592 EFIAPI
InitializeUsbDebugHardware(IN USB_DEBUG_PORT_HANDLE * Handle)593 InitializeUsbDebugHardware (
594   IN USB_DEBUG_PORT_HANDLE *Handle
595 )
596 {
597   RETURN_STATUS             Status;
598   USB_DEBUG_PORT_REGISTER   *UsbDebugPortRegister;
599   USB_DEBUG_PORT_DESCRIPTOR UsbDebugPortDescriptor;
600   UINT32                    *PortStatus;
601   UINT32                    *UsbCmd;
602   UINT32                    *UsbStatus;
603   UINT32                    *UsbHCSParam;
604   UINT8                     DebugPortNumber;
605   UINT8                     Length;
606 
607   UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);
608   UsbHCSParam = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x04);
609   UsbCmd      = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x20);
610   UsbStatus   = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x24);
611 
612   //
613   // Check if the debug port is enabled and owned by myself.
614   //
615   if (((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE))
616        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE)) || (Handle->Initialized == USBDBG_RESET)) {
617     DEBUG ((
618       EFI_D_INFO,
619       "UsbDbg: Need to reset the host controller. ControlStatus = %08x\n",
620       MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)
621       ));
622     //
623     // If the host controller is halted, then reset and restart it.
624     //
625     if ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0) {
626       DEBUG ((EFI_D_INFO, "UsbDbg: Reset the host controller.\n"));
627       //
628       // reset the host controller.
629       //
630       MmioOr32((UINTN)UsbCmd, BIT1);
631       //
632       // ensure that the host controller is reset.
633       //
634       while ((MmioRead32((UINTN)UsbCmd) & BIT1) != 0);
635 
636       MmioOr32((UINTN)UsbCmd, BIT0);
637       // ensure that the host controller is started (HALTED bit must be cleared)
638       while ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0);
639     }
640 
641     //
642     // First get the ownership of port 0.
643     //
644     MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE);
645 
646     MicroSecondDelay (200000);
647   }
648   //
649   // Find out which port is used as debug port.
650   //
651   DebugPortNumber = (UINT8)((MmioRead32((UINTN)UsbHCSParam) & 0x00F00000) >> 20);
652   //
653   // Should find a device is connected at debug port
654   //
655   PortStatus = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);
656   if (!(MmioRead32((UINTN)PortStatus) & BIT0)) {
657     Handle->Initialized = USBDBG_NO_DEV;
658     return RETURN_NOT_FOUND;
659   }
660 
661   if (Handle->Initialized != USBDBG_INIT_DONE ||
662       (MmioRead32 ((UINTN) &UsbDebugPortRegister->ControlStatus) & USB_DEBUG_PORT_ENABLE) == 0) {
663     DEBUG ((EFI_D_INFO, "UsbDbg: Reset the debug port.\n"));
664     //
665     // Reset the debug port
666     //
667     MmioOr32((UINTN)PortStatus, BIT8);
668     MicroSecondDelay (500000);
669     MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);
670     while (MmioRead32((UINTN)PortStatus) & BIT8);
671 
672     //
673     // The port enabled bit should be set by HW.
674     //
675     if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {
676       Handle->Initialized = USBDBG_NO_DBG_CAB;
677       return RETURN_DEVICE_ERROR;
678     }
679 
680     //
681     // Enable Usb Debug Port Capability
682     //
683     MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE);
684 
685     //
686     // initialize the data toggle used by bulk in/out endpoint.
687     //
688     Handle->BulkInToggle  = 0;
689     Handle->BulkOutToggle = 0;
690 
691     //
692     // set usb debug device address as 0x7F.
693     //
694     Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mDebugCommunicationLibUsbSetDebugAddress, 0x0, 0x0, NULL, NULL);
695     if (RETURN_ERROR(Status)) {
696       //
697       // The device can not work well.
698       //
699       Handle->Initialized = USBDBG_NO_DBG_CAB;
700       return Status;
701     }
702 
703     //
704     // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.
705     //
706     Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);
707 
708     //
709     // Get debug descriptor.
710     //
711     Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mDebugCommunicationLibUsbGetDebugDescriptor, 0x7F, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);
712     if (RETURN_ERROR(Status)) {
713       //
714       // The device is not a usb debug device.
715       //
716       Handle->Initialized = USBDBG_NO_DBG_CAB;
717       return Status;
718     }
719 
720     if (Length != sizeof(USB_DEBUG_PORT_DESCRIPTOR)) {
721       Handle->Initialized = USBDBG_NO_DBG_CAB;
722       return RETURN_DEVICE_ERROR;
723     }
724 
725     //
726     // enable the usb debug feature.
727     //
728     Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mDebugCommunicationLibUsbSetDebugFeature, 0x7F, 0x0, NULL, NULL);
729     if (RETURN_ERROR(Status)) {
730       //
731       // The device can not work well.
732       //
733       Handle->Initialized = USBDBG_NO_DBG_CAB;
734       return Status;
735     }
736 
737     Handle->Initialized = USBDBG_DBG_CAB;
738   }
739 
740   //
741   // Set initialized flag
742   //
743   Handle->Initialized = USBDBG_INIT_DONE;
744 
745   return RETURN_SUCCESS;
746 }
747 
748 /**
749   Read data from debug device and save the datas in buffer.
750 
751   Reads NumberOfBytes data bytes from a debug device into the buffer
752   specified by Buffer. The number of bytes actually read is returned.
753   If the return value is less than NumberOfBytes, then the rest operation failed.
754   If NumberOfBytes is zero, then return 0.
755 
756   @param  Handle           Debug port handle.
757   @param  Buffer           Pointer to the data buffer to store the data read from the debug device.
758   @param  NumberOfBytes    Number of bytes which will be read.
759   @param  Timeout          Timeout value for reading from debug device. It unit is Microsecond.
760 
761   @retval 0                Read data failed, no data is to be read.
762   @retval >0               Actual number of bytes read from debug device.
763 
764 **/
765 UINTN
766 EFIAPI
DebugPortReadBuffer(IN DEBUG_PORT_HANDLE Handle,IN UINT8 * Buffer,IN UINTN NumberOfBytes,IN UINTN Timeout)767 DebugPortReadBuffer (
768   IN   DEBUG_PORT_HANDLE    Handle,
769   IN   UINT8                *Buffer,
770   IN   UINTN                NumberOfBytes,
771   IN   UINTN                Timeout
772   )
773 {
774   USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
775   RETURN_STATUS             Status;
776   UINT8                     Index;
777 
778   if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
779     return 0;
780   }
781 
782   //
783   // If Handle is NULL, it means memory is ready for use.
784   // Use global variable to store handle value.
785   //
786   if (Handle == NULL) {
787     UsbDebugPortHandle = &mDebugCommunicationLibUsbDebugPortHandle;
788   } else {
789     UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
790   }
791 
792   if (NeedReinitializeHardware(UsbDebugPortHandle)) {
793     Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
794     if (RETURN_ERROR(Status)) {
795       return 0;
796     }
797   }
798 
799   //
800   // Read data from buffer
801   //
802   if (UsbDebugPortHandle->DataCount < 1) {
803     return 0;
804   } else {
805     *Buffer = UsbDebugPortHandle->Data[0];
806     for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
807       if ((Index + 1) >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {
808         return 0;
809       }
810       UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Index + 1];
811     }
812     UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
813     return 1;
814   }
815 }
816 
817 /**
818   Write data from buffer to debug device.
819 
820   Writes NumberOfBytes data bytes from Buffer to the debug device.
821   The number of bytes actually written to the debug device is returned.
822   If the return value is less than NumberOfBytes, then the write operation failed.
823   If NumberOfBytes is zero, then return 0.
824 
825   @param  Handle           Debug port handle.
826   @param  Buffer           Pointer to the data buffer to be written.
827   @param  NumberOfBytes    Number of bytes to written to the debug device.
828 
829   @retval 0                NumberOfBytes is 0.
830   @retval >0               The number of bytes written to the debug device.
831                            If this value is less than NumberOfBytes, then the read operation failed.
832 
833 **/
834 UINTN
835 EFIAPI
DebugPortWriteBuffer(IN DEBUG_PORT_HANDLE Handle,IN UINT8 * Buffer,IN UINTN NumberOfBytes)836 DebugPortWriteBuffer (
837   IN   DEBUG_PORT_HANDLE    Handle,
838   IN   UINT8                *Buffer,
839   IN   UINTN                NumberOfBytes
840   )
841 {
842   USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
843   USB_DEBUG_PORT_REGISTER   *UsbDebugPortRegister;
844   RETURN_STATUS             Status;
845   UINT8                     Sent;
846   UINTN                     Total;
847   UINT8                     ReceivedPid;
848 
849   if (NumberOfBytes == 0 || Buffer == NULL) {
850     return 0;
851   }
852 
853   Sent  = 0;
854   Total = 0;
855 
856   //
857   // If Handle is NULL, it means memory is ready for use.
858   // Use global variable to store handle value.
859   //
860   if (Handle == NULL) {
861     UsbDebugPortHandle = &mDebugCommunicationLibUsbDebugPortHandle;
862   } else {
863     UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
864   }
865 
866   if (NeedReinitializeHardware(UsbDebugPortHandle)) {
867     Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
868     if (RETURN_ERROR(Status)) {
869       return 0;
870     }
871   }
872 
873   UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);
874 
875   while ((Total < NumberOfBytes)) {
876     if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
877       Sent = USB_DEBUG_PORT_MAX_PACKET_SIZE;
878     } else {
879       Sent = (UINT8)(NumberOfBytes - Total);
880     }
881 
882     Status = UsbDebugPortOut(UsbDebugPortRegister, Buffer + Total, Sent, OUTPUT_PID, 0x7F, 0x01, UsbDebugPortHandle->BulkOutToggle);
883 
884     if (RETURN_ERROR(Status)) {
885       return Total;
886     }
887 
888     ReceivedPid = (MmioRead8((UINTN)&UsbDebugPortRegister->ReceivedPid));
889     //
890     // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.
891     // should send the packet again.
892     //
893     if (ReceivedPid == NAK_PID) {
894       Sent = 0;
895     } else {
896       UsbDebugPortHandle->BulkOutToggle ^= 1;
897     }
898     Total += Sent;
899   }
900   return Total;
901 }
902 
903 /**
904   Polls a debug device to see if there is any data waiting to be read.
905 
906   Polls a debug device to see if there is any data waiting to be read.
907   If there is data waiting to be read from the debug device, then TRUE is returned.
908   If there is no data waiting to be read from the debug device, then FALSE is returned.
909 
910   @param  Handle           Debug port handle.
911 
912   @retval TRUE             Data is waiting to be read from the debug device.
913   @retval FALSE            There is no data waiting to be read from the serial device.
914 
915 **/
916 BOOLEAN
917 EFIAPI
DebugPortPollBuffer(IN DEBUG_PORT_HANDLE Handle)918 DebugPortPollBuffer (
919   IN DEBUG_PORT_HANDLE      Handle
920   )
921 {
922   USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
923   USB_DEBUG_PORT_REGISTER   *UsbDebugPortRegister;
924   UINT8                     Length;
925   UINT8                     Index;
926   RETURN_STATUS             Status;
927 
928   //
929   // If Handle is NULL, it means memory is ready for use.
930   // Use global variable to store handle value.
931   //
932   if (Handle == NULL) {
933     UsbDebugPortHandle = &mDebugCommunicationLibUsbDebugPortHandle;
934   } else {
935     UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
936   }
937 
938   if (NeedReinitializeHardware(UsbDebugPortHandle)) {
939     Status = InitializeUsbDebugHardware(UsbDebugPortHandle);
940     if (RETURN_ERROR(Status)) {
941       return FALSE;
942     }
943   }
944 
945   //
946   // If the data buffer is not empty, then return TRUE directly.
947   // else initialize a usb read transaction and read data to the data buffer.
948   //
949   if (UsbDebugPortHandle->DataCount != 0) {
950     return TRUE;
951   }
952 
953   UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);
954 
955   UsbDebugPortRegister->TokenPid = INPUT_PID;
956   if (UsbDebugPortHandle->BulkInToggle == 0) {
957     UsbDebugPortRegister->SendPid  = DATA0_PID;
958   } else {
959     UsbDebugPortRegister->SendPid  = DATA1_PID;
960   }
961   UsbDebugPortRegister->UsbAddress  = 0x7F;
962   UsbDebugPortRegister->UsbEndPoint = 0x82 & 0x0F;
963 
964   //
965   // Clearing W/R bit to indicate it's a READ operation
966   //
967   MmioAnd32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)~BIT4);
968   //
969   // Setting GO bit as well as clearing DONE bit
970   //
971   MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)BIT5);
972 
973   //
974   // Wait for completing the request
975   //
976   while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {
977     if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))
978        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {
979       return FALSE;
980     }
981   }
982 
983   if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)) & BIT6) {
984     return FALSE;
985   }
986 
987   Length = (UINT8)(MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & 0xF);
988 
989   if (Length > 8) {
990     return FALSE;
991   }
992 
993   UsbDebugPortHandle->BulkInToggle ^= 1;
994 
995   if (Length == 0) {
996     return FALSE;
997   }
998 
999   for (Index = 0; Index < Length; Index++) {
1000     UsbDebugPortHandle->Data[Index] = UsbDebugPortRegister->DataBuffer[Index];
1001   }
1002   UsbDebugPortHandle->DataCount = Length;
1003 
1004   return TRUE;
1005 }
1006 
1007 /**
1008   Initialize the debug port.
1009 
1010   If Function is not NULL, Debug Communication Library will call this function
1011   by passing in the Context to be the first parameter. If needed, Debug Communication
1012   Library will create one debug port handle to be the second argument passing in
1013   calling the Function, otherwise it will pass NULL to be the second argument of
1014   Function.
1015 
1016   If Function is NULL, and Context is not NULL, the Debug Communication Library could
1017     a) Return the same handle as passed in (as Context parameter).
1018     b) Ignore the input Context parameter and create new handle to be returned.
1019 
1020   If parameter Function is NULL and Context is NULL, Debug Communication Library could
1021   created a new handle if needed and return it, otherwise it will return NULL.
1022 
1023   @param[in] Context      Context needed by callback function; it was optional.
1024   @param[in] Function     Continue function called by Debug Communication library;
1025                           it was optional.
1026 
1027   @return  The debug port handle created by Debug Communication Library if Function
1028            is not NULL.
1029 
1030 **/
1031 DEBUG_PORT_HANDLE
1032 EFIAPI
DebugPortInitialize(IN VOID * Context,IN DEBUG_PORT_CONTINUE Function)1033 DebugPortInitialize (
1034   IN VOID                 *Context,
1035   IN DEBUG_PORT_CONTINUE  Function
1036   )
1037 {
1038   RETURN_STATUS             Status;
1039   USB_DEBUG_PORT_HANDLE     Handle;
1040 
1041   //
1042   // Validate the PCD PcdDebugPortHandleBufferSize value
1043   //
1044   ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB_DEBUG_PORT_HANDLE));
1045 
1046   if (Function == NULL && Context != NULL) {
1047     return (DEBUG_PORT_HANDLE *) Context;
1048   }
1049   ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));
1050 
1051   Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);
1052   if (RETURN_ERROR (Status)) {
1053     DEBUG ((EFI_D_ERROR, "UsbDbg: the pci device pointed by PcdUsbEhciPciAddress is not EHCI host controller or does not support debug port capability!\n"));
1054     goto Exit;
1055   }
1056 
1057   Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
1058 
1059   if (Handle.EhciMemoryBase == 0) {
1060     //
1061     // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
1062     //
1063     PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, PcdGet32(PcdUsbEhciMemorySpaceBase));
1064     Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
1065   }
1066 
1067   Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);
1068 
1069   if (Handle.UsbDebugPortMemoryBase == 0) {
1070     //
1071     // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
1072     //
1073     PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase));
1074     Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);
1075   }
1076 
1077   Handle.Initialized = USBDBG_RESET;
1078 
1079   if (NeedReinitializeHardware(&Handle)) {
1080     DEBUG ((EFI_D_ERROR, "UsbDbg: Start EHCI debug port initialization!\n"));
1081     Status = InitializeUsbDebugHardware (&Handle);
1082     if (RETURN_ERROR(Status)) {
1083       DEBUG ((EFI_D_ERROR, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));
1084       goto Exit;
1085     }
1086   }
1087 
1088 Exit:
1089 
1090   if (Function != NULL) {
1091     Function (Context, &Handle);
1092   } else {
1093     CopyMem(&mDebugCommunicationLibUsbDebugPortHandle, &Handle, sizeof (USB_DEBUG_PORT_HANDLE));
1094   }
1095 
1096   return (DEBUG_PORT_HANDLE)(UINTN)&mDebugCommunicationLibUsbDebugPortHandle;
1097 }
1098 
1099