TianoCore EDK2 master
Loading...
Searching...
No Matches
UsbPeim.c
Go to the documentation of this file.
1
10#include "UsbPeim.h"
11#include "HubPeim.h"
12#include "PeiUsbLib.h"
13
14//
15// UsbIo PPI interface function
16//
17PEI_USB_IO_PPI mUsbIoPpi = {
23};
24
25EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
26 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
27 &gPeiUsbIoPpiGuid,
28 NULL
29};
30
45 IN EFI_PEI_SERVICES **PeiServices,
48 );
49
65 IN EFI_PEI_SERVICES **PeiServices,
66 IN PEI_USB_DEVICE *PeiUsbDevice,
67 IN UINT8 Port,
68 IN OUT UINT8 *DeviceAddress
69 );
70
84 IN EFI_PEI_SERVICES **PeiServices,
85 IN PEI_USB_DEVICE *PeiUsbDevice
86 );
87
103 IN UINT8 *Buffer,
104 IN UINTN Length,
105 IN UINT8 DescType,
106 IN UINT8 DescLength,
107 OUT UINTN *ParsedBytes
108 );
109
122EFIAPI
124 IN EFI_PEI_FILE_HANDLE FileHandle,
125 IN CONST EFI_PEI_SERVICES **PeiServices
126 )
127{
128 EFI_STATUS Status;
129 UINTN Index;
132
133 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
134 return EFI_SUCCESS;
135 }
136
137 //
138 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
139 // be produced at the same time
140 //
141 Index = 0;
142 while (TRUE) {
143 //
144 // Get UsbHcPpi at first.
145 //
146 Status = PeiServicesLocatePpi (
147 &gPeiUsbHostControllerPpiGuid,
148 Index,
149 NULL,
150 (VOID **)&UsbHcPpi
151 );
152 if (EFI_ERROR (Status)) {
153 //
154 // No more host controller, break out
155 //
156 break;
157 }
158
159 PeiUsbEnumeration ((EFI_PEI_SERVICES **)PeiServices, UsbHcPpi, NULL);
160 Index++;
161 }
162
163 if (Index == 0) {
164 //
165 // Then try to get Usb2HcPpi.
166 //
167 while (TRUE) {
168 Status = PeiServicesLocatePpi (
169 &gPeiUsb2HostControllerPpiGuid,
170 Index,
171 NULL,
172 (VOID **)&Usb2HcPpi
173 );
174 if (EFI_ERROR (Status)) {
175 //
176 // No more host controller, break out
177 //
178 break;
179 }
180
181 PeiUsbEnumeration ((EFI_PEI_SERVICES **)PeiServices, NULL, Usb2HcPpi);
182 Index++;
183 }
184 }
185
186 if (Index == 0) {
187 return EFI_UNSUPPORTED;
188 }
189
190 return EFI_SUCCESS;
191}
192
208 IN EFI_PEI_SERVICES **PeiServices,
209 IN PEI_USB_DEVICE *PeiUsbDevice,
210 IN UINT8 *CurrentAddress
211 )
212{
213 UINTN Index;
214 EFI_STATUS Status;
215 PEI_USB_IO_PPI *UsbIoPpi;
216 EFI_USB_PORT_STATUS PortStatus;
217 UINTN MemPages;
219 PEI_USB_DEVICE *NewPeiUsbDevice;
220 UINTN InterfaceIndex;
221 UINTN EndpointIndex;
222
223 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
224
225 DEBUG ((DEBUG_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));
226
227 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
228 Status = PeiHubGetPortStatus (
229 PeiServices,
230 UsbIoPpi,
231 (UINT8)(Index + 1),
232 (UINT32 *)&PortStatus
233 );
234
235 if (EFI_ERROR (Status)) {
236 continue;
237 }
238
239 DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
240 //
241 // Only handle connection/enable/overcurrent/reset change.
242 //
243 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
244 continue;
245 } else {
246 if (IsPortConnect (PortStatus.PortStatus)) {
247 //
248 // Begin to deal with the new device
249 //
250 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
251 Status = PeiServicesAllocatePages (
253 MemPages,
255 );
256 if (EFI_ERROR (Status)) {
257 return EFI_OUT_OF_RESOURCES;
258 }
259
260 NewPeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
261 ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
262
263 NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
264 NewPeiUsbDevice->DeviceAddress = 0;
265 NewPeiUsbDevice->MaxPacketSize0 = 8;
266 NewPeiUsbDevice->DataToggle = 0;
267 CopyMem (
268 &(NewPeiUsbDevice->UsbIoPpi),
269 &mUsbIoPpi,
270 sizeof (PEI_USB_IO_PPI)
271 );
272 CopyMem (
273 &(NewPeiUsbDevice->UsbIoPpiList),
274 &mUsbIoPpiList,
276 );
277 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
278 NewPeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
279 NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;
280 NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;
281 NewPeiUsbDevice->Tier = (UINT8)(PeiUsbDevice->Tier + 1);
282 NewPeiUsbDevice->IsHub = 0x0;
283 NewPeiUsbDevice->DownStreamPortNo = 0x0;
284
285 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
286 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))
287 {
288 //
289 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
290 //
291 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
292
294 PeiServices,
295 UsbIoPpi,
296 (UINT8)(Index + 1),
297 (UINT32 *)&PortStatus
298 );
299 } else {
301 PeiServices,
302 UsbIoPpi,
303 (UINT8)(Index + 1),
304 EfiUsbPortResetChange
305 );
306 }
307
308 NewPeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
309 DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
310
311 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
312 NewPeiUsbDevice->MaxPacketSize0 = 512;
313 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
314 NewPeiUsbDevice->MaxPacketSize0 = 64;
315 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
316 NewPeiUsbDevice->MaxPacketSize0 = 8;
317 } else {
318 NewPeiUsbDevice->MaxPacketSize0 = 8;
319 }
320
321 if (NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
322 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
323 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;
324 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;
325 } else {
326 CopyMem (&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR));
327 }
328 }
329
330 //
331 // Configure that Usb Device
332 //
333 Status = PeiConfigureUsbDevice (
334 PeiServices,
335 NewPeiUsbDevice,
336 (UINT8)(Index + 1),
337 CurrentAddress
338 );
339
340 if (EFI_ERROR (Status)) {
341 continue;
342 }
343
344 DEBUG ((DEBUG_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
345
346 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
347
348 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
349 NewPeiUsbDevice->IsHub = 0x1;
350
351 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
352 if (EFI_ERROR (Status)) {
353 return Status;
354 }
355
356 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
357 }
358
359 for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
360 //
361 // Begin to deal with the new device
362 //
363 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
364 Status = PeiServicesAllocatePages (
366 MemPages,
368 );
369 if (EFI_ERROR (Status)) {
370 return EFI_OUT_OF_RESOURCES;
371 }
372
373 CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
374 NewPeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
375 NewPeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
376 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
377 NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];
378 for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
379 NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
380 }
381
382 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
383
384 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
385 NewPeiUsbDevice->IsHub = 0x1;
386
387 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
388 if (EFI_ERROR (Status)) {
389 return Status;
390 }
391
392 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
393 }
394 }
395 }
396 }
397 }
398
399 return EFI_SUCCESS;
400}
401
416 IN EFI_PEI_SERVICES **PeiServices,
419 )
420{
421 UINT8 NumOfRootPort;
422 EFI_STATUS Status;
423 UINT8 Index;
424 EFI_USB_PORT_STATUS PortStatus;
425 PEI_USB_DEVICE *PeiUsbDevice;
426 UINTN MemPages;
428 UINT8 CurrentAddress;
429 UINTN InterfaceIndex;
430 UINTN EndpointIndex;
431
432 CurrentAddress = 0;
433 if (Usb2HcPpi != NULL) {
434 Usb2HcPpi->GetRootHubPortNumber (
435 PeiServices,
436 Usb2HcPpi,
437 (UINT8 *)&NumOfRootPort
438 );
439 } else if (UsbHcPpi != NULL) {
440 UsbHcPpi->GetRootHubPortNumber (
441 PeiServices,
442 UsbHcPpi,
443 (UINT8 *)&NumOfRootPort
444 );
445 } else {
446 ASSERT (FALSE);
447 return EFI_INVALID_PARAMETER;
448 }
449
450 DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
451
452 for (Index = 0; Index < NumOfRootPort; Index++) {
453 //
454 // First get root port status to detect changes happen
455 //
456 if (Usb2HcPpi != NULL) {
457 Usb2HcPpi->GetRootHubPortStatus (
458 PeiServices,
459 Usb2HcPpi,
460 (UINT8)Index,
461 &PortStatus
462 );
463 } else {
464 UsbHcPpi->GetRootHubPortStatus (
465 PeiServices,
466 UsbHcPpi,
467 (UINT8)Index,
468 &PortStatus
469 );
470 }
471
472 DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
473 //
474 // Only handle connection/enable/overcurrent/reset change.
475 //
476 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
477 continue;
478 } else {
479 if (IsPortConnect (PortStatus.PortStatus)) {
480 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
481 Status = PeiServicesAllocatePages (
483 MemPages,
485 );
486 if (EFI_ERROR (Status)) {
487 return EFI_OUT_OF_RESOURCES;
488 }
489
490 PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
491 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
492
493 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
494 PeiUsbDevice->DeviceAddress = 0;
495 PeiUsbDevice->MaxPacketSize0 = 8;
496 PeiUsbDevice->DataToggle = 0;
497 CopyMem (
498 &(PeiUsbDevice->UsbIoPpi),
499 &mUsbIoPpi,
500 sizeof (PEI_USB_IO_PPI)
501 );
502 CopyMem (
503 &(PeiUsbDevice->UsbIoPpiList),
504 &mUsbIoPpiList,
506 );
507 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
508 PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
509 PeiUsbDevice->UsbHcPpi = UsbHcPpi;
510 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
511 PeiUsbDevice->IsHub = 0x0;
512 PeiUsbDevice->DownStreamPortNo = 0x0;
513
514 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
515 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))
516 {
517 //
518 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
519 //
521 PeiServices,
522 PeiUsbDevice->UsbHcPpi,
523 PeiUsbDevice->Usb2HcPpi,
524 Index,
525 0
526 );
527
528 if (Usb2HcPpi != NULL) {
529 Usb2HcPpi->GetRootHubPortStatus (
530 PeiServices,
531 Usb2HcPpi,
532 (UINT8)Index,
533 &PortStatus
534 );
535 } else {
536 UsbHcPpi->GetRootHubPortStatus (
537 PeiServices,
538 UsbHcPpi,
539 (UINT8)Index,
540 &PortStatus
541 );
542 }
543 } else {
544 if (Usb2HcPpi != NULL) {
545 Usb2HcPpi->ClearRootHubPortFeature (
546 PeiServices,
547 Usb2HcPpi,
548 (UINT8)Index,
549 EfiUsbPortResetChange
550 );
551 } else {
552 UsbHcPpi->ClearRootHubPortFeature (
553 PeiServices,
554 UsbHcPpi,
555 (UINT8)Index,
556 EfiUsbPortResetChange
557 );
558 }
559 }
560
561 PeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
562 DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
563
564 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
565 PeiUsbDevice->MaxPacketSize0 = 512;
566 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
567 PeiUsbDevice->MaxPacketSize0 = 64;
568 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
569 PeiUsbDevice->MaxPacketSize0 = 8;
570 } else {
571 PeiUsbDevice->MaxPacketSize0 = 8;
572 }
573
574 //
575 // Configure that Usb Device
576 //
577 Status = PeiConfigureUsbDevice (
578 PeiServices,
579 PeiUsbDevice,
580 Index,
581 &CurrentAddress
582 );
583
584 if (EFI_ERROR (Status)) {
585 continue;
586 }
587
588 DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
589
590 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
591
592 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
593 PeiUsbDevice->IsHub = 0x1;
594
595 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
596 if (EFI_ERROR (Status)) {
597 return Status;
598 }
599
600 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
601 }
602
603 for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
604 //
605 // Begin to deal with the new device
606 //
607 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
608 Status = PeiServicesAllocatePages (
610 MemPages,
612 );
613 if (EFI_ERROR (Status)) {
614 return EFI_OUT_OF_RESOURCES;
615 }
616
617 CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
618 PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
619 PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
620 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
621 PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
622 for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
623 PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
624 }
625
626 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
627
628 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
629 PeiUsbDevice->IsHub = 0x1;
630
631 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
632 if (EFI_ERROR (Status)) {
633 return Status;
634 }
635
636 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
637 }
638 }
639 } else {
640 //
641 // Disconnect change happen, currently we don't support
642 //
643 }
644 }
645 }
646
647 return EFI_SUCCESS;
648}
649
665 IN EFI_PEI_SERVICES **PeiServices,
666 IN PEI_USB_DEVICE *PeiUsbDevice,
667 IN UINT8 Port,
668 IN OUT UINT8 *DeviceAddress
669 )
670{
671 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
672 EFI_STATUS Status;
673 PEI_USB_IO_PPI *UsbIoPpi;
674 UINT8 Retry;
675
676 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
677 Status = EFI_SUCCESS;
678 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
679 //
680 // Get USB device descriptor
681 //
682
683 for (Retry = 0; Retry < 3; Retry++) {
684 Status = PeiUsbGetDescriptor (
685 PeiServices,
686 UsbIoPpi,
687 (USB_DT_DEVICE << 8),
688 0,
689 8,
690 &DeviceDescriptor
691 );
692
693 if (!EFI_ERROR (Status)) {
694 DEBUG ((DEBUG_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));
695 break;
696 }
697 }
698
699 if (Retry == 3) {
700 DEBUG ((DEBUG_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));
701 return Status;
702 }
703
704 if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {
705 PeiUsbDevice->MaxPacketSize0 = 1 << 9;
706 } else {
707 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
708 }
709
710 (*DeviceAddress)++;
711
712 Status = PeiUsbSetDeviceAddress (
713 PeiServices,
714 UsbIoPpi,
715 *DeviceAddress
716 );
717
718 if (EFI_ERROR (Status)) {
719 DEBUG ((DEBUG_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));
720 return Status;
721 }
722
723 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);
724
725 PeiUsbDevice->DeviceAddress = *DeviceAddress;
726
727 //
728 // Get whole USB device descriptor
729 //
730 Status = PeiUsbGetDescriptor (
731 PeiServices,
732 UsbIoPpi,
733 (USB_DT_DEVICE << 8),
734 0,
735 (UINT16)sizeof (EFI_USB_DEVICE_DESCRIPTOR),
736 &DeviceDescriptor
737 );
738
739 if (EFI_ERROR (Status)) {
740 DEBUG ((DEBUG_ERROR, "PeiUsbGetDescriptor First Failed\n"));
741 return Status;
742 }
743
744 //
745 // Get its default configuration and its first interface
746 //
748 PeiServices,
749 PeiUsbDevice
750 );
751 if (EFI_ERROR (Status)) {
752 return Status;
753 }
754
755 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
756
757 Status = PeiUsbSetConfiguration (
758 PeiServices,
759 UsbIoPpi
760 );
761
762 if (EFI_ERROR (Status)) {
763 return Status;
764 }
765
766 return EFI_SUCCESS;
767}
768
782 IN EFI_PEI_SERVICES **PeiServices,
783 IN PEI_USB_DEVICE *PeiUsbDevice
784 )
785{
786 EFI_STATUS Status;
787 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
788 PEI_USB_IO_PPI *UsbIoPpi;
789 UINT16 ConfigDescLength;
790 UINT8 *Ptr;
791 UINTN SkipBytes;
792 UINTN LengthLeft;
793 UINTN InterfaceIndex;
794 UINTN Index;
795 UINTN NumOfEndpoint;
796
797 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
798
799 //
800 // First get its 4-byte configuration descriptor
801 //
802 Status = PeiUsbGetDescriptor (
803 PeiServices,
804 UsbIoPpi,
805 (USB_DT_CONFIG << 8), // Value
806 0, // Index
807 4, // Length
808 PeiUsbDevice->ConfigurationData
809 );
810
811 if (EFI_ERROR (Status)) {
812 DEBUG ((DEBUG_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));
813 return Status;
814 }
815
816 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
817
818 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *)PeiUsbDevice->ConfigurationData;
819 ConfigDescLength = ConfigDesc->TotalLength;
820
821 //
822 // Reject if TotalLength even cannot cover itself.
823 //
824 if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) {
825 return EFI_DEVICE_ERROR;
826 }
827
828 //
829 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.
830 //
831 if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) {
832 return EFI_DEVICE_ERROR;
833 }
834
835 //
836 // Then we get the total descriptors for this configuration
837 //
838 Status = PeiUsbGetDescriptor (
839 PeiServices,
840 UsbIoPpi,
841 (USB_DT_CONFIG << 8),
842 0,
843 ConfigDescLength,
844 PeiUsbDevice->ConfigurationData
845 );
846
847 if (EFI_ERROR (Status)) {
848 DEBUG ((DEBUG_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));
849 return Status;
850 }
851
852 //
853 // Parse this configuration descriptor
854 // First get the current config descriptor;
855 //
856 Status = GetExpectedDescriptor (
857 PeiUsbDevice->ConfigurationData,
858 ConfigDescLength,
859 USB_DT_CONFIG,
860 (UINT8)sizeof (EFI_USB_CONFIG_DESCRIPTOR),
861 &SkipBytes
862 );
863
864 if (EFI_ERROR (Status)) {
865 return Status;
866 }
867
868 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;
869 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *)Ptr;
870
871 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
872 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
873
874 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
875 //
876 // Get the interface descriptor
877 //
878 Status = GetExpectedDescriptor (
879 Ptr,
880 LengthLeft,
881 USB_DT_INTERFACE,
882 (UINT8)sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
883 &SkipBytes
884 );
885
886 if (EFI_ERROR (Status)) {
887 return Status;
888 }
889
890 Ptr += SkipBytes;
891 if (InterfaceIndex == 0) {
892 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)Ptr;
893 }
894
895 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *)Ptr;
896
897 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
898 LengthLeft -= SkipBytes;
899 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
900
901 //
902 // Parse all the endpoint descriptor within this interface
903 //
904 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;
905 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);
906
907 for (Index = 0; Index < NumOfEndpoint; Index++) {
908 //
909 // Get the endpoint descriptor
910 //
911 Status = GetExpectedDescriptor (
912 Ptr,
913 LengthLeft,
914 USB_DT_ENDPOINT,
915 (UINT8)sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
916 &SkipBytes
917 );
918
919 if (EFI_ERROR (Status)) {
920 return Status;
921 }
922
923 Ptr += SkipBytes;
924 if (InterfaceIndex == 0) {
925 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *)Ptr;
926 }
927
928 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *)Ptr;
929
930 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
931 LengthLeft -= SkipBytes;
932 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
933 }
934 }
935
936 return EFI_SUCCESS;
937}
938
954 IN UINT8 *Buffer,
955 IN UINTN Length,
956 IN UINT8 DescType,
957 IN UINT8 DescLength,
958 OUT UINTN *ParsedBytes
959 )
960{
961 USB_DESC_HEAD *Head;
962 UINTN Offset;
963
964 //
965 // Total length is too small that cannot hold the single descriptor header plus data.
966 //
967 if (Length <= sizeof (USB_DESC_HEAD)) {
968 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));
969 return EFI_DEVICE_ERROR;
970 }
971
972 //
973 // All the descriptor has a common LTV (Length, Type, Value)
974 // format. Skip the descriptor that isn't of this Type
975 //
976 Offset = 0;
977 Head = (USB_DESC_HEAD *)Buffer;
978 while (Offset < Length - sizeof (USB_DESC_HEAD)) {
979 //
980 // Above condition make sure Head->Len and Head->Type are safe to access
981 //
982 Head = (USB_DESC_HEAD *)&Buffer[Offset];
983
984 if (Head->Len == 0) {
985 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));
986 return EFI_DEVICE_ERROR;
987 }
988
989 //
990 // Make sure no overflow when adding Head->Len to Offset.
991 //
992 if (Head->Len > MAX_UINTN - Offset) {
993 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));
994 return EFI_DEVICE_ERROR;
995 }
996
997 if (Head->Type == DescType) {
998 break;
999 }
1000
1001 Offset += Head->Len;
1002 }
1003
1004 //
1005 // Head->Len is invalid resulting data beyond boundary, or
1006 // Descriptor cannot be found: No such type.
1007 //
1008 if (Length < Offset) {
1009 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));
1010 return EFI_DEVICE_ERROR;
1011 }
1012
1013 if ((Head->Type != DescType) || (Head->Len < DescLength)) {
1014 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));
1015 return EFI_DEVICE_ERROR;
1016 }
1017
1018 *ParsedBytes = Offset;
1019 return EFI_SUCCESS;
1020}
1021
1032VOID
1034 IN EFI_PEI_SERVICES **PeiServices,
1037 IN UINT8 PortNum,
1038 IN UINT8 RetryIndex
1039 )
1040{
1041 EFI_STATUS Status;
1042 UINTN Index;
1043 EFI_USB_PORT_STATUS PortStatus;
1044
1045 if (Usb2HcPpi != NULL) {
1046 MicroSecondDelay (200 * 1000);
1047
1048 //
1049 // reset root port
1050 //
1051 Status = Usb2HcPpi->SetRootHubPortFeature (
1052 PeiServices,
1053 Usb2HcPpi,
1054 PortNum,
1055 EfiUsbPortReset
1056 );
1057
1058 if (EFI_ERROR (Status)) {
1059 DEBUG ((DEBUG_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1060 return;
1061 }
1062
1063 //
1064 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1065 // section 7.1.7.5 for timing requirements.
1066 //
1067 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
1068
1069 //
1070 // clear reset root port
1071 //
1072 Status = Usb2HcPpi->ClearRootHubPortFeature (
1073 PeiServices,
1074 Usb2HcPpi,
1075 PortNum,
1076 EfiUsbPortReset
1077 );
1078
1079 if (EFI_ERROR (Status)) {
1080 DEBUG ((DEBUG_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1081 return;
1082 }
1083
1084 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
1085
1086 //
1087 // USB host controller won't clear the RESET bit until
1088 // reset is actually finished.
1089 //
1090 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
1091
1092 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1093 Status = Usb2HcPpi->GetRootHubPortStatus (
1094 PeiServices,
1095 Usb2HcPpi,
1096 PortNum,
1097 &PortStatus
1098 );
1099 if (EFI_ERROR (Status)) {
1100 return;
1101 }
1102
1103 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
1104 break;
1105 }
1106
1107 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
1108 }
1109
1110 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1111 DEBUG ((DEBUG_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
1112 return;
1113 }
1114
1115 Usb2HcPpi->ClearRootHubPortFeature (
1116 PeiServices,
1117 Usb2HcPpi,
1118 PortNum,
1119 EfiUsbPortResetChange
1120 );
1121
1122 Usb2HcPpi->ClearRootHubPortFeature (
1123 PeiServices,
1124 Usb2HcPpi,
1125 PortNum,
1126 EfiUsbPortConnectChange
1127 );
1128
1129 //
1130 // Set port enable
1131 //
1132 Usb2HcPpi->SetRootHubPortFeature (
1133 PeiServices,
1134 Usb2HcPpi,
1135 PortNum,
1136 EfiUsbPortEnable
1137 );
1138
1139 Usb2HcPpi->ClearRootHubPortFeature (
1140 PeiServices,
1141 Usb2HcPpi,
1142 PortNum,
1143 EfiUsbPortEnableChange
1144 );
1145
1146 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1147 } else {
1148 MicroSecondDelay (200 * 1000);
1149
1150 //
1151 // reset root port
1152 //
1153 Status = UsbHcPpi->SetRootHubPortFeature (
1154 PeiServices,
1155 UsbHcPpi,
1156 PortNum,
1157 EfiUsbPortReset
1158 );
1159
1160 if (EFI_ERROR (Status)) {
1161 DEBUG ((DEBUG_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1162 return;
1163 }
1164
1165 //
1166 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1167 // section 7.1.7.5 for timing requirements.
1168 //
1169 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
1170
1171 //
1172 // clear reset root port
1173 //
1174 Status = UsbHcPpi->ClearRootHubPortFeature (
1175 PeiServices,
1176 UsbHcPpi,
1177 PortNum,
1178 EfiUsbPortReset
1179 );
1180
1181 if (EFI_ERROR (Status)) {
1182 DEBUG ((DEBUG_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1183 return;
1184 }
1185
1186 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
1187
1188 //
1189 // USB host controller won't clear the RESET bit until
1190 // reset is actually finished.
1191 //
1192 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
1193
1194 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1195 Status = UsbHcPpi->GetRootHubPortStatus (
1196 PeiServices,
1197 UsbHcPpi,
1198 PortNum,
1199 &PortStatus
1200 );
1201 if (EFI_ERROR (Status)) {
1202 return;
1203 }
1204
1205 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
1206 break;
1207 }
1208
1209 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
1210 }
1211
1212 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1213 DEBUG ((DEBUG_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
1214 return;
1215 }
1216
1217 UsbHcPpi->ClearRootHubPortFeature (
1218 PeiServices,
1219 UsbHcPpi,
1220 PortNum,
1221 EfiUsbPortResetChange
1222 );
1223
1224 UsbHcPpi->ClearRootHubPortFeature (
1225 PeiServices,
1226 UsbHcPpi,
1227 PortNum,
1228 EfiUsbPortConnectChange
1229 );
1230
1231 //
1232 // Set port enable
1233 //
1234 UsbHcPpi->SetRootHubPortFeature (
1235 PeiServices,
1236 UsbHcPpi,
1237 PortNum,
1238 EfiUsbPortEnable
1239 );
1240
1241 UsbHcPpi->ClearRootHubPortFeature (
1242 PeiServices,
1243 UsbHcPpi,
1244 PortNum,
1245 EfiUsbPortEnableChange
1246 );
1247
1248 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1249 }
1250
1251 return;
1252}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
EFI_STATUS EFIAPI PeiServicesAllocatePages(IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT EFI_PHYSICAL_ADDRESS *Memory)
EFI_STATUS EFIAPI PeiServicesInstallPpi(IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList)
EFI_STATUS EFIAPI PeiServicesRegisterForShadow(IN EFI_PEI_FILE_HANDLE FileHandle)
EFI_STATUS PeiHubClearPortFeature(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *UsbIoPpi, IN UINT8 Port, IN UINT8 Value)
Definition: HubPeim.c:116
EFI_STATUS PeiDoHubConfig(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_DEVICE *PeiUsbDevice)
Definition: HubPeim.c:373
VOID PeiResetHubPort(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *UsbIoPpi, IN UINT8 PortNum)
Definition: HubPeim.c:484
EFI_STATUS PeiHubGetPortStatus(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *UsbIoPpi, IN UINT8 Port, OUT UINT32 *PortStatus)
Definition: HubPeim.c:28
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define USB_PORT_STAT_C_CONNECTION
#define USB_PORT_STAT_CONNECTION
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
@ EfiBootServicesCode
@ AllocateAddress
Definition: UefiSpec.h:42
EFI_STATUS PeiUsbSetDeviceAddress(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *UsbIoPpi, IN UINT16 AddressValue)
Definition: PeiUsbLib.c:73
EFI_STATUS PeiUsbGetDescriptor(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *UsbIoPpi, IN UINT16 Value, IN UINT16 Index, IN UINT16 DescriptorLength, OUT VOID *Descriptor)
Definition: PeiUsbLib.c:30
UINTN PeiUsbGetDeviceSpeed(IN UINT16 PortStatus)
Definition: PeiUsbLib.c:169
EFI_STATUS PeiUsbSetConfiguration(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *UsbIoPpi)
Definition: PeiUsbLib.c:112
BOOLEAN IsPortConnect(IN UINT16 PortStatus)
Definition: PeiUsbLib.c:146
EFI_STATUS EFIAPI PeiUsbBulkTransfer(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *This, IN UINT8 DeviceEndpoint, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN UINTN Timeout)
Definition: UsbIoPeim.c:151
EFI_STATUS EFIAPI PeiUsbGetInterfaceDescriptor(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *This, OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor)
Definition: UsbIoPeim.c:254
EFI_STATUS EFIAPI PeiUsbControlTransfer(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *This, IN EFI_USB_DEVICE_REQUEST *Request, IN EFI_USB_DATA_DIRECTION Direction, IN UINT32 Timeout, IN OUT VOID *Data OPTIONAL, IN UINTN DataLength OPTIONAL)
Definition: UsbIoPeim.c:35
EFI_STATUS EFIAPI PeiUsbGetEndpointDescriptor(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *This, IN UINT8 EndpointIndex, OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor)
Definition: UsbIoPeim.c:281
EFI_STATUS EFIAPI PeiUsbPortReset(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_IO_PPI *This)
Definition: UsbIoPeim.c:322
EFI_STATUS PeiConfigureUsbDevice(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_DEVICE *PeiUsbDevice, IN UINT8 Port, IN OUT UINT8 *DeviceAddress)
Definition: UsbPeim.c:664
VOID ResetRootPort(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi, IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi, IN UINT8 PortNum, IN UINT8 RetryIndex)
Definition: UsbPeim.c:1033
EFI_STATUS PeiHubEnumeration(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_DEVICE *PeiUsbDevice, IN UINT8 *CurrentAddress)
Definition: UsbPeim.c:207
EFI_STATUS EFIAPI PeimInitializeUsb(IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices)
Definition: UsbPeim.c:123
EFI_STATUS GetExpectedDescriptor(IN UINT8 *Buffer, IN UINTN Length, IN UINT8 DescType, IN UINT8 DescLength, OUT UINTN *ParsedBytes)
Definition: UsbPeim.c:953
EFI_STATUS PeiUsbEnumeration(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi, IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi)
Definition: UsbPeim.c:415
EFI_STATUS PeiUsbGetAllConfiguration(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_DEVICE *PeiUsbDevice)
Definition: UsbPeim.c:781
UINT8 TranslatorPortNumber
the port number of the hub that device is connected to.
UINT16 PortChangeStatus
Contains current port status change bitmap.
UINT16 PortStatus
Contains current port status bitmap.