MdeModulePkg UsbBusPei: Produce a USB I/O PPI for all USB Interfaces a USB Device...
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbPeim.c
1 /** @file
2 The module to produce Usb Bus PPI.
3
4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "UsbPeim.h"
18 #include "HubPeim.h"
19 #include "PeiUsbLib.h"
20
21 //
22 // UsbIo PPI interface function
23 //
24 PEI_USB_IO_PPI mUsbIoPpi = {
25 PeiUsbControlTransfer,
26 PeiUsbBulkTransfer,
27 PeiUsbGetInterfaceDescriptor,
28 PeiUsbGetEndpointDescriptor,
29 PeiUsbPortReset
30 };
31
32 EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34 &gPeiUsbIoPpiGuid,
35 NULL
36 };
37
38 /**
39 The enumeration routine to detect device change.
40
41 @param PeiServices Describes the list of possible PEI Services.
42 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
43 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
44
45 @retval EFI_SUCCESS The usb is enumerated successfully.
46 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
47 @retval Others Other failure occurs.
48
49 **/
50 EFI_STATUS
51 PeiUsbEnumeration (
52 IN EFI_PEI_SERVICES **PeiServices,
53 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
54 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi
55 );
56
57 /**
58 Configure new detected usb device.
59
60 @param PeiServices Describes the list of possible PEI Services.
61 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
62 @param Port The port to be configured.
63 @param DeviceAddress The device address to be configured.
64
65 @retval EFI_SUCCESS The new detected usb device is configured successfully.
66 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
67 @retval Others Other failure occurs.
68
69 **/
70 EFI_STATUS
71 PeiConfigureUsbDevice (
72 IN EFI_PEI_SERVICES **PeiServices,
73 IN PEI_USB_DEVICE *PeiUsbDevice,
74 IN UINT8 Port,
75 IN OUT UINT8 *DeviceAddress
76 );
77
78 /**
79 Get all configurations from a detected usb device.
80
81 @param PeiServices Describes the list of possible PEI Services.
82 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
83
84 @retval EFI_SUCCESS The new detected usb device is configured successfully.
85 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
86 @retval Others Other failure occurs.
87
88 **/
89 EFI_STATUS
90 PeiUsbGetAllConfiguration (
91 IN EFI_PEI_SERVICES **PeiServices,
92 IN PEI_USB_DEVICE *PeiUsbDevice
93 );
94
95 /**
96 Get the start position of next wanted descriptor.
97
98 @param Buffer Buffer containing data to parse.
99 @param Length Buffer length.
100 @param DescType Descriptor type.
101 @param DescLength Descriptor length.
102 @param ParsedBytes Bytes has been parsed.
103
104 @retval EFI_SUCCESS Get wanted descriptor successfully.
105 @retval EFI_DEVICE_ERROR Error occurred.
106
107 **/
108 EFI_STATUS
109 GetExpectedDescriptor (
110 IN UINT8 *Buffer,
111 IN UINTN Length,
112 IN UINT8 DescType,
113 IN UINT8 DescLength,
114 OUT UINTN *ParsedBytes
115 );
116
117 /**
118 The entrypoint of the module, it will enumerate all HCs.
119
120 @param FileHandle Handle of the file being invoked.
121 @param PeiServices Describes the list of possible PEI Services.
122
123 @retval EFI_SUCCESS Usb initialization is done successfully.
124 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
125 @retval EFI_UNSUPPORTED Can't find required PPI.
126
127 **/
128 EFI_STATUS
129 EFIAPI
130 PeimInitializeUsb (
131 IN EFI_PEI_FILE_HANDLE FileHandle,
132 IN CONST EFI_PEI_SERVICES **PeiServices
133 )
134 {
135 EFI_STATUS Status;
136 UINTN Index;
137 PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
138 PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
139
140 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
141 return EFI_SUCCESS;
142 }
143
144 //
145 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
146 // be produced at the same time
147 //
148 Index = 0;
149 while (TRUE) {
150 //
151 // Get UsbHcPpi at first.
152 //
153 Status = PeiServicesLocatePpi (
154 &gPeiUsbHostControllerPpiGuid,
155 Index,
156 NULL,
157 (VOID **) &UsbHcPpi
158 );
159 if (EFI_ERROR (Status)) {
160 //
161 // No more host controller, break out
162 //
163 break;
164 }
165 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);
166 Index++;
167 }
168
169 if (Index == 0) {
170 //
171 // Then try to get Usb2HcPpi.
172 //
173 while (TRUE) {
174 Status = PeiServicesLocatePpi (
175 &gPeiUsb2HostControllerPpiGuid,
176 Index,
177 NULL,
178 (VOID **) &Usb2HcPpi
179 );
180 if (EFI_ERROR (Status)) {
181 //
182 // No more host controller, break out
183 //
184 break;
185 }
186 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);
187 Index++;
188 }
189 }
190
191 if (Index == 0) {
192 return EFI_UNSUPPORTED;
193 }
194
195 return EFI_SUCCESS;
196 }
197
198 /**
199 The Hub Enumeration just scans the hub ports one time. It also
200 doesn't support hot-plug.
201
202 @param PeiServices Describes the list of possible PEI Services.
203 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
204 @param CurrentAddress The DeviceAddress of usb device.
205
206 @retval EFI_SUCCESS The usb hub is enumerated successfully.
207 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
208 @retval Others Other failure occurs.
209
210 **/
211 EFI_STATUS
212 PeiHubEnumeration (
213 IN EFI_PEI_SERVICES **PeiServices,
214 IN PEI_USB_DEVICE *PeiUsbDevice,
215 IN UINT8 *CurrentAddress
216 )
217 {
218 UINTN Index;
219 EFI_STATUS Status;
220 PEI_USB_IO_PPI *UsbIoPpi;
221 EFI_USB_PORT_STATUS PortStatus;
222 UINTN MemPages;
223 EFI_PHYSICAL_ADDRESS AllocateAddress;
224 PEI_USB_DEVICE *NewPeiUsbDevice;
225 UINTN InterfaceIndex;
226 UINTN EndpointIndex;
227
228
229 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
230
231 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
232
233 Status = PeiHubGetPortStatus (
234 PeiServices,
235 UsbIoPpi,
236 (UINT8) (Index + 1),
237 (UINT32 *) &PortStatus
238 );
239
240 if (EFI_ERROR (Status)) {
241 continue;
242 }
243
244 if (IsPortConnectChange (PortStatus.PortChangeStatus)) {
245 PeiHubClearPortFeature (
246 PeiServices,
247 UsbIoPpi,
248 (UINT8) (Index + 1),
249 EfiUsbPortConnectChange
250 );
251
252 MicroSecondDelay (100 * 1000);
253
254 if (IsPortConnect (PortStatus.PortStatus)) {
255
256 PeiHubGetPortStatus (
257 PeiServices,
258 UsbIoPpi,
259 (UINT8) (Index + 1),
260 (UINT32 *) &PortStatus
261 );
262
263 //
264 // Begin to deal with the new device
265 //
266 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
267 Status = PeiServicesAllocatePages (
268 EfiBootServicesCode,
269 MemPages,
270 &AllocateAddress
271 );
272 if (EFI_ERROR (Status)) {
273 return EFI_OUT_OF_RESOURCES;
274 }
275
276 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
277 ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
278
279 NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
280 NewPeiUsbDevice->DeviceAddress = 0;
281 NewPeiUsbDevice->MaxPacketSize0 = 8;
282 NewPeiUsbDevice->DataToggle = 0;
283 CopyMem (
284 &(NewPeiUsbDevice->UsbIoPpi),
285 &mUsbIoPpi,
286 sizeof (PEI_USB_IO_PPI)
287 );
288 CopyMem (
289 &(NewPeiUsbDevice->UsbIoPpiList),
290 &mUsbIoPpiList,
291 sizeof (EFI_PEI_PPI_DESCRIPTOR)
292 );
293 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
294 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
295 NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;
296 NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;
297 NewPeiUsbDevice->IsHub = 0x0;
298 NewPeiUsbDevice->DownStreamPortNo = 0x0;
299
300 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
301
302 PeiHubGetPortStatus (
303 PeiServices,
304 UsbIoPpi,
305 (UINT8) (Index + 1),
306 (UINT32 *) &PortStatus
307 );
308
309 NewPeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);
310
311 if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
312 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
313 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;
314 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;
315 } else {
316 CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));
317 }
318 }
319
320 //
321 // Configure that Usb Device
322 //
323 Status = PeiConfigureUsbDevice (
324 PeiServices,
325 NewPeiUsbDevice,
326 (UINT8) (Index + 1),
327 CurrentAddress
328 );
329
330 if (EFI_ERROR (Status)) {
331 continue;
332 }
333
334 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
335
336 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
337 NewPeiUsbDevice->IsHub = 0x1;
338
339 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
340 if (EFI_ERROR (Status)) {
341 return Status;
342 }
343
344 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
345 }
346
347 for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
348 //
349 // Begin to deal with the new device
350 //
351 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
352 Status = PeiServicesAllocatePages (
353 EfiBootServicesCode,
354 MemPages,
355 &AllocateAddress
356 );
357 if (EFI_ERROR (Status)) {
358 return EFI_OUT_OF_RESOURCES;
359 }
360 CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
361 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
362 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
363 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
364 NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];
365 for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
366 NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
367 }
368
369 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
370
371 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
372 NewPeiUsbDevice->IsHub = 0x1;
373
374 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
375 if (EFI_ERROR (Status)) {
376 return Status;
377 }
378
379 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
380 }
381 }
382 }
383 }
384 }
385
386
387 return EFI_SUCCESS;
388 }
389
390 /**
391 The enumeration routine to detect device change.
392
393 @param PeiServices Describes the list of possible PEI Services.
394 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
395 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
396
397 @retval EFI_SUCCESS The usb is enumerated successfully.
398 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
399 @retval Others Other failure occurs.
400
401 **/
402 EFI_STATUS
403 PeiUsbEnumeration (
404 IN EFI_PEI_SERVICES **PeiServices,
405 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
406 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi
407 )
408 {
409 UINT8 NumOfRootPort;
410 EFI_STATUS Status;
411 UINT8 Index;
412 EFI_USB_PORT_STATUS PortStatus;
413 PEI_USB_DEVICE *PeiUsbDevice;
414 UINTN MemPages;
415 EFI_PHYSICAL_ADDRESS AllocateAddress;
416 UINT8 CurrentAddress;
417 UINTN InterfaceIndex;
418 UINTN EndpointIndex;
419
420 CurrentAddress = 0;
421 if (Usb2HcPpi != NULL) {
422 Usb2HcPpi->GetRootHubPortNumber (
423 PeiServices,
424 Usb2HcPpi,
425 (UINT8 *) &NumOfRootPort
426 );
427 } else if (UsbHcPpi != NULL) {
428 UsbHcPpi->GetRootHubPortNumber (
429 PeiServices,
430 UsbHcPpi,
431 (UINT8 *) &NumOfRootPort
432 );
433 } else {
434 ASSERT (FALSE);
435 return EFI_INVALID_PARAMETER;
436 }
437
438 for (Index = 0; Index < NumOfRootPort; Index++) {
439 //
440 // First get root port status to detect changes happen
441 //
442 if (Usb2HcPpi != NULL) {
443 Usb2HcPpi->GetRootHubPortStatus (
444 PeiServices,
445 Usb2HcPpi,
446 (UINT8) Index,
447 &PortStatus
448 );
449 } else {
450 UsbHcPpi->GetRootHubPortStatus (
451 PeiServices,
452 UsbHcPpi,
453 (UINT8) Index,
454 &PortStatus
455 );
456 }
457 DEBUG ((EFI_D_INFO, "USB Status --- ConnectChange[%04x] Status[%04x]\n", PortStatus.PortChangeStatus, PortStatus.PortStatus));
458 if (IsPortConnectChange (PortStatus.PortChangeStatus)) {
459 //
460 // Changes happen, first clear this change status
461 //
462 if (Usb2HcPpi != NULL) {
463 Usb2HcPpi->ClearRootHubPortFeature (
464 PeiServices,
465 Usb2HcPpi,
466 (UINT8) Index,
467 EfiUsbPortConnectChange
468 );
469 } else {
470 UsbHcPpi->ClearRootHubPortFeature (
471 PeiServices,
472 UsbHcPpi,
473 (UINT8) Index,
474 EfiUsbPortConnectChange
475 );
476 }
477 MicroSecondDelay (100 * 1000);
478
479 if (IsPortConnect (PortStatus.PortStatus)) {
480 if (Usb2HcPpi != NULL) {
481 Usb2HcPpi->GetRootHubPortStatus (
482 PeiServices,
483 Usb2HcPpi,
484 (UINT8) Index,
485 &PortStatus
486 );
487 } else {
488 UsbHcPpi->GetRootHubPortStatus (
489 PeiServices,
490 UsbHcPpi,
491 (UINT8) Index,
492 &PortStatus
493 );
494 }
495
496 //
497 // Connect change happen
498 //
499 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
500 Status = PeiServicesAllocatePages (
501 EfiBootServicesCode,
502 MemPages,
503 &AllocateAddress
504 );
505 if (EFI_ERROR (Status)) {
506 return EFI_OUT_OF_RESOURCES;
507 }
508
509 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
510 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
511
512 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
513 PeiUsbDevice->DeviceAddress = 0;
514 PeiUsbDevice->MaxPacketSize0 = 8;
515 PeiUsbDevice->DataToggle = 0;
516 CopyMem (
517 &(PeiUsbDevice->UsbIoPpi),
518 &mUsbIoPpi,
519 sizeof (PEI_USB_IO_PPI)
520 );
521 CopyMem (
522 &(PeiUsbDevice->UsbIoPpiList),
523 &mUsbIoPpiList,
524 sizeof (EFI_PEI_PPI_DESCRIPTOR)
525 );
526 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
527 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
528 PeiUsbDevice->UsbHcPpi = UsbHcPpi;
529 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
530 PeiUsbDevice->IsHub = 0x0;
531 PeiUsbDevice->DownStreamPortNo = 0x0;
532
533 ResetRootPort (
534 PeiServices,
535 PeiUsbDevice->UsbHcPpi,
536 PeiUsbDevice->Usb2HcPpi,
537 Index,
538 0
539 );
540
541 if (Usb2HcPpi != NULL) {
542 Usb2HcPpi->GetRootHubPortStatus (
543 PeiServices,
544 Usb2HcPpi,
545 (UINT8) Index,
546 &PortStatus
547 );
548 } else {
549 UsbHcPpi->GetRootHubPortStatus (
550 PeiServices,
551 UsbHcPpi,
552 (UINT8) Index,
553 &PortStatus
554 );
555 }
556
557 PeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);
558 DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
559
560 //
561 // Configure that Usb Device
562 //
563 Status = PeiConfigureUsbDevice (
564 PeiServices,
565 PeiUsbDevice,
566 Index,
567 &CurrentAddress
568 );
569
570 if (EFI_ERROR (Status)) {
571 continue;
572 }
573 DEBUG ((EFI_D_INFO, "PeiConfigureUsbDevice Success\n"));
574
575 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
576
577 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
578 PeiUsbDevice->IsHub = 0x1;
579
580 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
581 if (EFI_ERROR (Status)) {
582 return Status;
583 }
584
585 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
586 }
587
588 for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
589 //
590 // Begin to deal with the new device
591 //
592 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
593 Status = PeiServicesAllocatePages (
594 EfiBootServicesCode,
595 MemPages,
596 &AllocateAddress
597 );
598 if (EFI_ERROR (Status)) {
599 return EFI_OUT_OF_RESOURCES;
600 }
601 CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
602 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
603 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
604 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
605 PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
606 for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
607 PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
608 }
609
610 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
611
612 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
613 PeiUsbDevice->IsHub = 0x1;
614
615 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
616 if (EFI_ERROR (Status)) {
617 return Status;
618 }
619
620 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
621 }
622 }
623 } else {
624 //
625 // Disconnect change happen, currently we don't support
626 //
627 }
628 }
629 }
630
631 return EFI_SUCCESS;
632 }
633
634 /**
635 Configure new detected usb device.
636
637 @param PeiServices Describes the list of possible PEI Services.
638 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
639 @param Port The port to be configured.
640 @param DeviceAddress The device address to be configured.
641
642 @retval EFI_SUCCESS The new detected usb device is configured successfully.
643 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
644 @retval Others Other failure occurs.
645
646 **/
647 EFI_STATUS
648 PeiConfigureUsbDevice (
649 IN EFI_PEI_SERVICES **PeiServices,
650 IN PEI_USB_DEVICE *PeiUsbDevice,
651 IN UINT8 Port,
652 IN OUT UINT8 *DeviceAddress
653 )
654 {
655 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
656 EFI_STATUS Status;
657 PEI_USB_IO_PPI *UsbIoPpi;
658 UINT8 Retry;
659
660 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
661 Status = EFI_SUCCESS;
662 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
663 //
664 // Get USB device descriptor
665 //
666
667 for (Retry = 0; Retry < 3; Retry ++) {
668
669 PeiUsbDevice->MaxPacketSize0 = 8;
670
671 Status = PeiUsbGetDescriptor (
672 PeiServices,
673 UsbIoPpi,
674 (USB_DT_DEVICE << 8),
675 0,
676 8,
677 &DeviceDescriptor
678 );
679
680 if (!EFI_ERROR (Status)) {
681 DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Sucess\n", Retry));
682 break;
683 }
684 }
685
686 if (Retry == 3) {
687 DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail\n", Retry));
688 return Status;
689 }
690
691 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
692
693 (*DeviceAddress) ++;
694
695 Status = PeiUsbSetDeviceAddress (
696 PeiServices,
697 UsbIoPpi,
698 *DeviceAddress
699 );
700
701 if (EFI_ERROR (Status)) {
702 DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed\n"));
703 return Status;
704 }
705
706 PeiUsbDevice->DeviceAddress = *DeviceAddress;
707
708 //
709 // Get whole USB device descriptor
710 //
711 Status = PeiUsbGetDescriptor (
712 PeiServices,
713 UsbIoPpi,
714 (USB_DT_DEVICE << 8),
715 0,
716 (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),
717 &DeviceDescriptor
718 );
719
720 if (EFI_ERROR (Status)) {
721 DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));
722 return Status;
723 }
724
725 //
726 // Get its default configuration and its first interface
727 //
728 Status = PeiUsbGetAllConfiguration (
729 PeiServices,
730 PeiUsbDevice
731 );
732 if (EFI_ERROR (Status)) {
733 return Status;
734 }
735
736 Status = PeiUsbSetConfiguration (
737 PeiServices,
738 UsbIoPpi
739 );
740
741 if (EFI_ERROR (Status)) {
742 return Status;
743 }
744
745 return EFI_SUCCESS;
746 }
747
748 /**
749 Get all configurations from a detected usb device.
750
751 @param PeiServices Describes the list of possible PEI Services.
752 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
753
754 @retval EFI_SUCCESS The new detected usb device is configured successfully.
755 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
756 @retval Others Other failure occurs.
757
758 **/
759 EFI_STATUS
760 PeiUsbGetAllConfiguration (
761 IN EFI_PEI_SERVICES **PeiServices,
762 IN PEI_USB_DEVICE *PeiUsbDevice
763 )
764 {
765 EFI_STATUS Status;
766 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
767 PEI_USB_IO_PPI *UsbIoPpi;
768 UINT16 ConfigDescLength;
769 UINT8 *Ptr;
770 UINTN SkipBytes;
771 UINTN LengthLeft;
772 UINTN InterfaceIndex;
773 UINTN Index;
774 UINTN NumOfEndpoint;
775
776 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
777
778 //
779 // First get its 4-byte configuration descriptor
780 //
781 Status = PeiUsbGetDescriptor (
782 PeiServices,
783 UsbIoPpi,
784 (USB_DT_CONFIG << 8), // Value
785 0, // Index
786 4, // Length
787 PeiUsbDevice->ConfigurationData
788 );
789
790 if (EFI_ERROR (Status)) {
791 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));
792 return Status;
793 }
794
795 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;
796 ConfigDescLength = ConfigDesc->TotalLength;
797
798 //
799 // Then we get the total descriptors for this configuration
800 //
801 Status = PeiUsbGetDescriptor (
802 PeiServices,
803 UsbIoPpi,
804 (USB_DT_CONFIG << 8),
805 0,
806 ConfigDescLength,
807 PeiUsbDevice->ConfigurationData
808 );
809
810 if (EFI_ERROR (Status)) {
811 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));
812 return Status;
813 }
814 //
815 // Parse this configuration descriptor
816 // First get the current config descriptor;
817 //
818 Status = GetExpectedDescriptor (
819 PeiUsbDevice->ConfigurationData,
820 ConfigDescLength,
821 USB_DT_CONFIG,
822 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),
823 &SkipBytes
824 );
825
826 if (EFI_ERROR (Status)) {
827 return Status;
828 }
829
830 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;
831 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;
832
833 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
834 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
835
836 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
837
838 //
839 // Get the interface descriptor
840 //
841 Status = GetExpectedDescriptor (
842 Ptr,
843 LengthLeft,
844 USB_DT_INTERFACE,
845 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
846 &SkipBytes
847 );
848
849 if (EFI_ERROR (Status)) {
850 return Status;
851 }
852
853 Ptr += SkipBytes;
854 if (InterfaceIndex == 0) {
855 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
856 }
857 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
858
859 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
860 LengthLeft -= SkipBytes;
861 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
862
863 //
864 // Parse all the endpoint descriptor within this interface
865 //
866 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;
867 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);
868
869 for (Index = 0; Index < NumOfEndpoint; Index++) {
870 //
871 // Get the endpoint descriptor
872 //
873 Status = GetExpectedDescriptor (
874 Ptr,
875 LengthLeft,
876 USB_DT_ENDPOINT,
877 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
878 &SkipBytes
879 );
880
881 if (EFI_ERROR (Status)) {
882 return Status;
883 }
884
885 Ptr += SkipBytes;
886 if (InterfaceIndex == 0) {
887 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
888 }
889 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
890
891 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
892 LengthLeft -= SkipBytes;
893 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
894 }
895 }
896
897 return EFI_SUCCESS;
898 }
899
900 /**
901 Get the start position of next wanted descriptor.
902
903 @param Buffer Buffer containing data to parse.
904 @param Length Buffer length.
905 @param DescType Descriptor type.
906 @param DescLength Descriptor length.
907 @param ParsedBytes Bytes has been parsed.
908
909 @retval EFI_SUCCESS Get wanted descriptor successfully.
910 @retval EFI_DEVICE_ERROR Error occurred.
911
912 **/
913 EFI_STATUS
914 GetExpectedDescriptor (
915 IN UINT8 *Buffer,
916 IN UINTN Length,
917 IN UINT8 DescType,
918 IN UINT8 DescLength,
919 OUT UINTN *ParsedBytes
920 )
921 {
922 UINT16 DescriptorHeader;
923 UINT8 Len;
924 UINT8 *Ptr;
925 UINTN Parsed;
926
927 Parsed = 0;
928 Ptr = Buffer;
929
930 while (TRUE) {
931 //
932 // Buffer length should not less than Desc length
933 //
934 if (Length < DescLength) {
935 return EFI_DEVICE_ERROR;
936 }
937
938 DescriptorHeader = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));
939
940 Len = Buffer[0];
941
942 //
943 // Check to see if it is a start of expected descriptor
944 //
945 if (DescriptorHeader == ((DescType << 8) | DescLength)) {
946 break;
947 }
948
949 if ((UINT8) (DescriptorHeader >> 8) == DescType) {
950 if (Len > DescLength) {
951 return EFI_DEVICE_ERROR;
952 }
953 }
954 //
955 // Descriptor length should be at least 2
956 // and should not exceed the buffer length
957 //
958 if (Len < 2) {
959 return EFI_DEVICE_ERROR;
960 }
961
962 if (Len > Length) {
963 return EFI_DEVICE_ERROR;
964 }
965 //
966 // Skip this mismatch descriptor
967 //
968 Length -= Len;
969 Ptr += Len;
970 Parsed += Len;
971 }
972
973 *ParsedBytes = Parsed;
974
975 return EFI_SUCCESS;
976 }
977
978 /**
979 Send reset signal over the given root hub port.
980
981 @param PeiServices Describes the list of possible PEI Services.
982 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
983 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
984 @param PortNum The port to be reset.
985 @param RetryIndex The retry times.
986
987 **/
988 VOID
989 ResetRootPort (
990 IN EFI_PEI_SERVICES **PeiServices,
991 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
992 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,
993 IN UINT8 PortNum,
994 IN UINT8 RetryIndex
995 )
996 {
997 EFI_STATUS Status;
998
999
1000 if (Usb2HcPpi != NULL) {
1001 MicroSecondDelay (200 * 1000);
1002
1003 //
1004 // reset root port
1005 //
1006 Status = Usb2HcPpi->SetRootHubPortFeature (
1007 PeiServices,
1008 Usb2HcPpi,
1009 PortNum,
1010 EfiUsbPortReset
1011 );
1012
1013 if (EFI_ERROR (Status)) {
1014 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1015 return;
1016 }
1017
1018 MicroSecondDelay (200 * 1000);
1019
1020 //
1021 // clear reset root port
1022 //
1023 Status = Usb2HcPpi->ClearRootHubPortFeature (
1024 PeiServices,
1025 Usb2HcPpi,
1026 PortNum,
1027 EfiUsbPortReset
1028 );
1029
1030 if (EFI_ERROR (Status)) {
1031 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1032 return;
1033 }
1034
1035 MicroSecondDelay (1 * 1000);
1036
1037 Usb2HcPpi->ClearRootHubPortFeature (
1038 PeiServices,
1039 Usb2HcPpi,
1040 PortNum,
1041 EfiUsbPortConnectChange
1042 );
1043
1044 //
1045 // Set port enable
1046 //
1047 Usb2HcPpi->SetRootHubPortFeature(
1048 PeiServices,
1049 Usb2HcPpi,
1050 PortNum,
1051 EfiUsbPortEnable
1052 );
1053
1054 Usb2HcPpi->ClearRootHubPortFeature (
1055 PeiServices,
1056 Usb2HcPpi,
1057 PortNum,
1058 EfiUsbPortEnableChange
1059 );
1060
1061 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1062 } else {
1063 MicroSecondDelay (200 * 1000);
1064
1065 //
1066 // reset root port
1067 //
1068 Status = UsbHcPpi->SetRootHubPortFeature (
1069 PeiServices,
1070 UsbHcPpi,
1071 PortNum,
1072 EfiUsbPortReset
1073 );
1074
1075 if (EFI_ERROR (Status)) {
1076 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1077 return;
1078 }
1079
1080 MicroSecondDelay (200 * 1000);
1081
1082 //
1083 // clear reset root port
1084 //
1085 Status = UsbHcPpi->ClearRootHubPortFeature (
1086 PeiServices,
1087 UsbHcPpi,
1088 PortNum,
1089 EfiUsbPortReset
1090 );
1091
1092 if (EFI_ERROR (Status)) {
1093 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1094 return;
1095 }
1096
1097 MicroSecondDelay (1 * 1000);
1098
1099 UsbHcPpi->ClearRootHubPortFeature (
1100 PeiServices,
1101 UsbHcPpi,
1102 PortNum,
1103 EfiUsbPortConnectChange
1104 );
1105
1106 //
1107 // Set port enable
1108 //
1109 UsbHcPpi->SetRootHubPortFeature(
1110 PeiServices,
1111 UsbHcPpi,
1112 PortNum,
1113 EfiUsbPortEnable
1114 );
1115
1116 UsbHcPpi->ClearRootHubPortFeature (
1117 PeiServices,
1118 UsbHcPpi,
1119 PortNum,
1120 EfiUsbPortEnableChange
1121 );
1122
1123 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1124 }
1125 return;
1126 }
1127
1128