]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
MdeModulePkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbPeim.c
1 /** @file
2 The module to produce Usb Bus PPI.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UsbPeim.h"
11 #include "HubPeim.h"
12 #include "PeiUsbLib.h"
13
14 //
15 // UsbIo PPI interface function
16 //
17 PEI_USB_IO_PPI mUsbIoPpi = {
18 PeiUsbControlTransfer,
19 PeiUsbBulkTransfer,
20 PeiUsbGetInterfaceDescriptor,
21 PeiUsbGetEndpointDescriptor,
22 PeiUsbPortReset
23 };
24
25 EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
26 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
27 &gPeiUsbIoPpiGuid,
28 NULL
29 };
30
31 /**
32 The enumeration routine to detect device change.
33
34 @param PeiServices Describes the list of possible PEI Services.
35 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
36 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
37
38 @retval EFI_SUCCESS The usb is enumerated successfully.
39 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
40 @retval Others Other failure occurs.
41
42 **/
43 EFI_STATUS
44 PeiUsbEnumeration (
45 IN EFI_PEI_SERVICES **PeiServices,
46 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
47 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi
48 );
49
50 /**
51 Configure new detected usb device.
52
53 @param PeiServices Describes the list of possible PEI Services.
54 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
55 @param Port The port to be configured.
56 @param DeviceAddress The device address to be configured.
57
58 @retval EFI_SUCCESS The new detected usb device is configured successfully.
59 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
60 @retval Others Other failure occurs.
61
62 **/
63 EFI_STATUS
64 PeiConfigureUsbDevice (
65 IN EFI_PEI_SERVICES **PeiServices,
66 IN PEI_USB_DEVICE *PeiUsbDevice,
67 IN UINT8 Port,
68 IN OUT UINT8 *DeviceAddress
69 );
70
71 /**
72 Get all configurations from a detected usb device.
73
74 @param PeiServices Describes the list of possible PEI Services.
75 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
76
77 @retval EFI_SUCCESS The new detected usb device is configured successfully.
78 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
79 @retval Others Other failure occurs.
80
81 **/
82 EFI_STATUS
83 PeiUsbGetAllConfiguration (
84 IN EFI_PEI_SERVICES **PeiServices,
85 IN PEI_USB_DEVICE *PeiUsbDevice
86 );
87
88 /**
89 Get the start position of next wanted descriptor.
90
91 @param Buffer Buffer containing data to parse.
92 @param Length Buffer length.
93 @param DescType Descriptor type.
94 @param DescLength Descriptor length.
95 @param ParsedBytes Bytes has been parsed.
96
97 @retval EFI_SUCCESS Get wanted descriptor successfully.
98 @retval EFI_DEVICE_ERROR Error occurred.
99
100 **/
101 EFI_STATUS
102 GetExpectedDescriptor (
103 IN UINT8 *Buffer,
104 IN UINTN Length,
105 IN UINT8 DescType,
106 IN UINT8 DescLength,
107 OUT UINTN *ParsedBytes
108 );
109
110 /**
111 The entrypoint of the module, it will enumerate all HCs.
112
113 @param FileHandle Handle of the file being invoked.
114 @param PeiServices Describes the list of possible PEI Services.
115
116 @retval EFI_SUCCESS Usb initialization is done successfully.
117 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
118 @retval EFI_UNSUPPORTED Can't find required PPI.
119
120 **/
121 EFI_STATUS
122 EFIAPI
123 PeimInitializeUsb (
124 IN EFI_PEI_FILE_HANDLE FileHandle,
125 IN CONST EFI_PEI_SERVICES **PeiServices
126 )
127 {
128 EFI_STATUS Status;
129 UINTN Index;
130 PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
131 PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
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 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);
159 Index++;
160 }
161
162 if (Index == 0) {
163 //
164 // Then try to get Usb2HcPpi.
165 //
166 while (TRUE) {
167 Status = PeiServicesLocatePpi (
168 &gPeiUsb2HostControllerPpiGuid,
169 Index,
170 NULL,
171 (VOID **) &Usb2HcPpi
172 );
173 if (EFI_ERROR (Status)) {
174 //
175 // No more host controller, break out
176 //
177 break;
178 }
179 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);
180 Index++;
181 }
182 }
183
184 if (Index == 0) {
185 return EFI_UNSUPPORTED;
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 The Hub Enumeration just scans the hub ports one time. It also
193 doesn't support hot-plug.
194
195 @param PeiServices Describes the list of possible PEI Services.
196 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
197 @param CurrentAddress The DeviceAddress of usb device.
198
199 @retval EFI_SUCCESS The usb hub is enumerated successfully.
200 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
201 @retval Others Other failure occurs.
202
203 **/
204 EFI_STATUS
205 PeiHubEnumeration (
206 IN EFI_PEI_SERVICES **PeiServices,
207 IN PEI_USB_DEVICE *PeiUsbDevice,
208 IN UINT8 *CurrentAddress
209 )
210 {
211 UINTN Index;
212 EFI_STATUS Status;
213 PEI_USB_IO_PPI *UsbIoPpi;
214 EFI_USB_PORT_STATUS PortStatus;
215 UINTN MemPages;
216 EFI_PHYSICAL_ADDRESS AllocateAddress;
217 PEI_USB_DEVICE *NewPeiUsbDevice;
218 UINTN InterfaceIndex;
219 UINTN EndpointIndex;
220
221
222 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
223
224 DEBUG ((DEBUG_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));
225
226 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
227
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 (
252 EfiBootServicesCode,
253 MemPages,
254 &AllocateAddress
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,
275 sizeof (EFI_PEI_PPI_DESCRIPTOR)
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 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
289 //
290 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
291
292 PeiHubGetPortStatus (
293 PeiServices,
294 UsbIoPpi,
295 (UINT8) (Index + 1),
296 (UINT32 *) &PortStatus
297 );
298 } else {
299 PeiHubClearPortFeature (
300 PeiServices,
301 UsbIoPpi,
302 (UINT8) (Index + 1),
303 EfiUsbPortResetChange
304 );
305 }
306
307 NewPeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
308 DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
309
310 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
311 NewPeiUsbDevice->MaxPacketSize0 = 512;
312 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
313 NewPeiUsbDevice->MaxPacketSize0 = 64;
314 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
315 NewPeiUsbDevice->MaxPacketSize0 = 8;
316 } else {
317 NewPeiUsbDevice->MaxPacketSize0 = 8;
318 }
319
320 if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
321 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
322 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;
323 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;
324 } else {
325 CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));
326 }
327 }
328
329 //
330 // Configure that Usb Device
331 //
332 Status = PeiConfigureUsbDevice (
333 PeiServices,
334 NewPeiUsbDevice,
335 (UINT8) (Index + 1),
336 CurrentAddress
337 );
338
339 if (EFI_ERROR (Status)) {
340 continue;
341 }
342 DEBUG ((DEBUG_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
343
344 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
345
346 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
347 NewPeiUsbDevice->IsHub = 0x1;
348
349 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353
354 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
355 }
356
357 for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
358 //
359 // Begin to deal with the new device
360 //
361 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
362 Status = PeiServicesAllocatePages (
363 EfiBootServicesCode,
364 MemPages,
365 &AllocateAddress
366 );
367 if (EFI_ERROR (Status)) {
368 return EFI_OUT_OF_RESOURCES;
369 }
370 CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
371 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
372 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
373 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
374 NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];
375 for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
376 NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
377 }
378
379 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
380
381 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
382 NewPeiUsbDevice->IsHub = 0x1;
383
384 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
385 if (EFI_ERROR (Status)) {
386 return Status;
387 }
388
389 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
390 }
391 }
392 }
393 }
394 }
395
396
397 return EFI_SUCCESS;
398 }
399
400 /**
401 The enumeration routine to detect device change.
402
403 @param PeiServices Describes the list of possible PEI Services.
404 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
405 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
406
407 @retval EFI_SUCCESS The usb is enumerated successfully.
408 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
409 @retval Others Other failure occurs.
410
411 **/
412 EFI_STATUS
413 PeiUsbEnumeration (
414 IN EFI_PEI_SERVICES **PeiServices,
415 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
416 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi
417 )
418 {
419 UINT8 NumOfRootPort;
420 EFI_STATUS Status;
421 UINT8 Index;
422 EFI_USB_PORT_STATUS PortStatus;
423 PEI_USB_DEVICE *PeiUsbDevice;
424 UINTN MemPages;
425 EFI_PHYSICAL_ADDRESS AllocateAddress;
426 UINT8 CurrentAddress;
427 UINTN InterfaceIndex;
428 UINTN EndpointIndex;
429
430 CurrentAddress = 0;
431 if (Usb2HcPpi != NULL) {
432 Usb2HcPpi->GetRootHubPortNumber (
433 PeiServices,
434 Usb2HcPpi,
435 (UINT8 *) &NumOfRootPort
436 );
437 } else if (UsbHcPpi != NULL) {
438 UsbHcPpi->GetRootHubPortNumber (
439 PeiServices,
440 UsbHcPpi,
441 (UINT8 *) &NumOfRootPort
442 );
443 } else {
444 ASSERT (FALSE);
445 return EFI_INVALID_PARAMETER;
446 }
447
448 DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
449
450 for (Index = 0; Index < NumOfRootPort; Index++) {
451 //
452 // First get root port status to detect changes happen
453 //
454 if (Usb2HcPpi != NULL) {
455 Usb2HcPpi->GetRootHubPortStatus (
456 PeiServices,
457 Usb2HcPpi,
458 (UINT8) Index,
459 &PortStatus
460 );
461 } else {
462 UsbHcPpi->GetRootHubPortStatus (
463 PeiServices,
464 UsbHcPpi,
465 (UINT8) Index,
466 &PortStatus
467 );
468 }
469 DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
470 //
471 // Only handle connection/enable/overcurrent/reset change.
472 //
473 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
474 continue;
475 } else {
476 if (IsPortConnect (PortStatus.PortStatus)) {
477 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
478 Status = PeiServicesAllocatePages (
479 EfiBootServicesCode,
480 MemPages,
481 &AllocateAddress
482 );
483 if (EFI_ERROR (Status)) {
484 return EFI_OUT_OF_RESOURCES;
485 }
486
487 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
488 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
489
490 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
491 PeiUsbDevice->DeviceAddress = 0;
492 PeiUsbDevice->MaxPacketSize0 = 8;
493 PeiUsbDevice->DataToggle = 0;
494 CopyMem (
495 &(PeiUsbDevice->UsbIoPpi),
496 &mUsbIoPpi,
497 sizeof (PEI_USB_IO_PPI)
498 );
499 CopyMem (
500 &(PeiUsbDevice->UsbIoPpiList),
501 &mUsbIoPpiList,
502 sizeof (EFI_PEI_PPI_DESCRIPTOR)
503 );
504 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
505 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
506 PeiUsbDevice->UsbHcPpi = UsbHcPpi;
507 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
508 PeiUsbDevice->IsHub = 0x0;
509 PeiUsbDevice->DownStreamPortNo = 0x0;
510
511 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
512 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
513 //
514 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
515 //
516 ResetRootPort (
517 PeiServices,
518 PeiUsbDevice->UsbHcPpi,
519 PeiUsbDevice->Usb2HcPpi,
520 Index,
521 0
522 );
523
524 if (Usb2HcPpi != NULL) {
525 Usb2HcPpi->GetRootHubPortStatus (
526 PeiServices,
527 Usb2HcPpi,
528 (UINT8) Index,
529 &PortStatus
530 );
531 } else {
532 UsbHcPpi->GetRootHubPortStatus (
533 PeiServices,
534 UsbHcPpi,
535 (UINT8) Index,
536 &PortStatus
537 );
538 }
539 } else {
540 if (Usb2HcPpi != NULL) {
541 Usb2HcPpi->ClearRootHubPortFeature (
542 PeiServices,
543 Usb2HcPpi,
544 (UINT8) Index,
545 EfiUsbPortResetChange
546 );
547 } else {
548 UsbHcPpi->ClearRootHubPortFeature (
549 PeiServices,
550 UsbHcPpi,
551 (UINT8) Index,
552 EfiUsbPortResetChange
553 );
554 }
555 }
556
557 PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
558 DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
559
560 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
561 PeiUsbDevice->MaxPacketSize0 = 512;
562 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
563 PeiUsbDevice->MaxPacketSize0 = 64;
564 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
565 PeiUsbDevice->MaxPacketSize0 = 8;
566 } else {
567 PeiUsbDevice->MaxPacketSize0 = 8;
568 }
569
570 //
571 // Configure that Usb Device
572 //
573 Status = PeiConfigureUsbDevice (
574 PeiServices,
575 PeiUsbDevice,
576 Index,
577 &CurrentAddress
578 );
579
580 if (EFI_ERROR (Status)) {
581 continue;
582 }
583 DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
584
585 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
586
587 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
588 PeiUsbDevice->IsHub = 0x1;
589
590 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
591 if (EFI_ERROR (Status)) {
592 return Status;
593 }
594
595 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
596 }
597
598 for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
599 //
600 // Begin to deal with the new device
601 //
602 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
603 Status = PeiServicesAllocatePages (
604 EfiBootServicesCode,
605 MemPages,
606 &AllocateAddress
607 );
608 if (EFI_ERROR (Status)) {
609 return EFI_OUT_OF_RESOURCES;
610 }
611 CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
612 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
613 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
614 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
615 PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
616 for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
617 PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
618 }
619
620 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
621
622 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
623 PeiUsbDevice->IsHub = 0x1;
624
625 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
626 if (EFI_ERROR (Status)) {
627 return Status;
628 }
629
630 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
631 }
632 }
633 } else {
634 //
635 // Disconnect change happen, currently we don't support
636 //
637 }
638 }
639 }
640
641 return EFI_SUCCESS;
642 }
643
644 /**
645 Configure new detected usb device.
646
647 @param PeiServices Describes the list of possible PEI Services.
648 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
649 @param Port The port to be configured.
650 @param DeviceAddress The device address to be configured.
651
652 @retval EFI_SUCCESS The new detected usb device is configured successfully.
653 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
654 @retval Others Other failure occurs.
655
656 **/
657 EFI_STATUS
658 PeiConfigureUsbDevice (
659 IN EFI_PEI_SERVICES **PeiServices,
660 IN PEI_USB_DEVICE *PeiUsbDevice,
661 IN UINT8 Port,
662 IN OUT UINT8 *DeviceAddress
663 )
664 {
665 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
666 EFI_STATUS Status;
667 PEI_USB_IO_PPI *UsbIoPpi;
668 UINT8 Retry;
669
670 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
671 Status = EFI_SUCCESS;
672 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
673 //
674 // Get USB device descriptor
675 //
676
677 for (Retry = 0; Retry < 3; Retry ++) {
678 Status = PeiUsbGetDescriptor (
679 PeiServices,
680 UsbIoPpi,
681 (USB_DT_DEVICE << 8),
682 0,
683 8,
684 &DeviceDescriptor
685 );
686
687 if (!EFI_ERROR (Status)) {
688 DEBUG ((DEBUG_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));
689 break;
690 }
691 }
692
693 if (Retry == 3) {
694 DEBUG ((DEBUG_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));
695 return Status;
696 }
697
698 if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {
699 PeiUsbDevice->MaxPacketSize0 = 1 << 9;
700 } else {
701 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
702 }
703
704 (*DeviceAddress) ++;
705
706 Status = PeiUsbSetDeviceAddress (
707 PeiServices,
708 UsbIoPpi,
709 *DeviceAddress
710 );
711
712 if (EFI_ERROR (Status)) {
713 DEBUG ((DEBUG_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));
714 return Status;
715 }
716 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);
717
718 PeiUsbDevice->DeviceAddress = *DeviceAddress;
719
720 //
721 // Get whole USB device descriptor
722 //
723 Status = PeiUsbGetDescriptor (
724 PeiServices,
725 UsbIoPpi,
726 (USB_DT_DEVICE << 8),
727 0,
728 (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),
729 &DeviceDescriptor
730 );
731
732 if (EFI_ERROR (Status)) {
733 DEBUG ((DEBUG_ERROR, "PeiUsbGetDescriptor First Failed\n"));
734 return Status;
735 }
736
737 //
738 // Get its default configuration and its first interface
739 //
740 Status = PeiUsbGetAllConfiguration (
741 PeiServices,
742 PeiUsbDevice
743 );
744 if (EFI_ERROR (Status)) {
745 return Status;
746 }
747 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
748
749 Status = PeiUsbSetConfiguration (
750 PeiServices,
751 UsbIoPpi
752 );
753
754 if (EFI_ERROR (Status)) {
755 return Status;
756 }
757
758 return EFI_SUCCESS;
759 }
760
761 /**
762 Get all configurations from a detected usb device.
763
764 @param PeiServices Describes the list of possible PEI Services.
765 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
766
767 @retval EFI_SUCCESS The new detected usb device is configured successfully.
768 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
769 @retval Others Other failure occurs.
770
771 **/
772 EFI_STATUS
773 PeiUsbGetAllConfiguration (
774 IN EFI_PEI_SERVICES **PeiServices,
775 IN PEI_USB_DEVICE *PeiUsbDevice
776 )
777 {
778 EFI_STATUS Status;
779 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
780 PEI_USB_IO_PPI *UsbIoPpi;
781 UINT16 ConfigDescLength;
782 UINT8 *Ptr;
783 UINTN SkipBytes;
784 UINTN LengthLeft;
785 UINTN InterfaceIndex;
786 UINTN Index;
787 UINTN NumOfEndpoint;
788
789 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
790
791 //
792 // First get its 4-byte configuration descriptor
793 //
794 Status = PeiUsbGetDescriptor (
795 PeiServices,
796 UsbIoPpi,
797 (USB_DT_CONFIG << 8), // Value
798 0, // Index
799 4, // Length
800 PeiUsbDevice->ConfigurationData
801 );
802
803 if (EFI_ERROR (Status)) {
804 DEBUG ((DEBUG_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));
805 return Status;
806 }
807 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
808
809 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;
810 ConfigDescLength = ConfigDesc->TotalLength;
811
812 //
813 // Reject if TotalLength even cannot cover itself.
814 //
815 if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) {
816 return EFI_DEVICE_ERROR;
817 }
818
819 //
820 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.
821 //
822 if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) {
823 return EFI_DEVICE_ERROR;
824 }
825
826 //
827 // Then we get the total descriptors for this configuration
828 //
829 Status = PeiUsbGetDescriptor (
830 PeiServices,
831 UsbIoPpi,
832 (USB_DT_CONFIG << 8),
833 0,
834 ConfigDescLength,
835 PeiUsbDevice->ConfigurationData
836 );
837
838 if (EFI_ERROR (Status)) {
839 DEBUG ((DEBUG_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));
840 return Status;
841 }
842 //
843 // Parse this configuration descriptor
844 // First get the current config descriptor;
845 //
846 Status = GetExpectedDescriptor (
847 PeiUsbDevice->ConfigurationData,
848 ConfigDescLength,
849 USB_DT_CONFIG,
850 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),
851 &SkipBytes
852 );
853
854 if (EFI_ERROR (Status)) {
855 return Status;
856 }
857
858 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;
859 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;
860
861 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
862 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
863
864 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
865
866 //
867 // Get the interface descriptor
868 //
869 Status = GetExpectedDescriptor (
870 Ptr,
871 LengthLeft,
872 USB_DT_INTERFACE,
873 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
874 &SkipBytes
875 );
876
877 if (EFI_ERROR (Status)) {
878 return Status;
879 }
880
881 Ptr += SkipBytes;
882 if (InterfaceIndex == 0) {
883 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
884 }
885 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
886
887 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
888 LengthLeft -= SkipBytes;
889 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
890
891 //
892 // Parse all the endpoint descriptor within this interface
893 //
894 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;
895 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);
896
897 for (Index = 0; Index < NumOfEndpoint; Index++) {
898 //
899 // Get the endpoint descriptor
900 //
901 Status = GetExpectedDescriptor (
902 Ptr,
903 LengthLeft,
904 USB_DT_ENDPOINT,
905 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
906 &SkipBytes
907 );
908
909 if (EFI_ERROR (Status)) {
910 return Status;
911 }
912
913 Ptr += SkipBytes;
914 if (InterfaceIndex == 0) {
915 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
916 }
917 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
918
919 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
920 LengthLeft -= SkipBytes;
921 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
922 }
923 }
924
925 return EFI_SUCCESS;
926 }
927
928 /**
929 Get the start position of next wanted descriptor.
930
931 @param Buffer Buffer containing data to parse.
932 @param Length Buffer length.
933 @param DescType Descriptor type.
934 @param DescLength Descriptor length.
935 @param ParsedBytes Bytes has been parsed.
936
937 @retval EFI_SUCCESS Get wanted descriptor successfully.
938 @retval EFI_DEVICE_ERROR Error occurred.
939
940 **/
941 EFI_STATUS
942 GetExpectedDescriptor (
943 IN UINT8 *Buffer,
944 IN UINTN Length,
945 IN UINT8 DescType,
946 IN UINT8 DescLength,
947 OUT UINTN *ParsedBytes
948 )
949 {
950 USB_DESC_HEAD *Head;
951 UINTN Offset;
952
953 //
954 // Total length is too small that cannot hold the single descriptor header plus data.
955 //
956 if (Length <= sizeof (USB_DESC_HEAD)) {
957 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));
958 return EFI_DEVICE_ERROR;
959 }
960
961 //
962 // All the descriptor has a common LTV (Length, Type, Value)
963 // format. Skip the descriptor that isn't of this Type
964 //
965 Offset = 0;
966 Head = (USB_DESC_HEAD *)Buffer;
967 while (Offset < Length - sizeof (USB_DESC_HEAD)) {
968 //
969 // Above condition make sure Head->Len and Head->Type are safe to access
970 //
971 Head = (USB_DESC_HEAD *)&Buffer[Offset];
972
973 if (Head->Len == 0) {
974 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));
975 return EFI_DEVICE_ERROR;
976 }
977
978 //
979 // Make sure no overflow when adding Head->Len to Offset.
980 //
981 if (Head->Len > MAX_UINTN - Offset) {
982 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));
983 return EFI_DEVICE_ERROR;
984 }
985
986 if (Head->Type == DescType) {
987 break;
988 }
989
990 Offset += Head->Len;
991 }
992
993 //
994 // Head->Len is invalid resulting data beyond boundary, or
995 // Descriptor cannot be found: No such type.
996 //
997 if (Length < Offset) {
998 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));
999 return EFI_DEVICE_ERROR;
1000 }
1001
1002 if ((Head->Type != DescType) || (Head->Len < DescLength)) {
1003 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));
1004 return EFI_DEVICE_ERROR;
1005 }
1006
1007 *ParsedBytes = Offset;
1008 return EFI_SUCCESS;
1009 }
1010
1011 /**
1012 Send reset signal over the given root hub port.
1013
1014 @param PeiServices Describes the list of possible PEI Services.
1015 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
1016 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
1017 @param PortNum The port to be reset.
1018 @param RetryIndex The retry times.
1019
1020 **/
1021 VOID
1022 ResetRootPort (
1023 IN EFI_PEI_SERVICES **PeiServices,
1024 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
1025 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,
1026 IN UINT8 PortNum,
1027 IN UINT8 RetryIndex
1028 )
1029 {
1030 EFI_STATUS Status;
1031 UINTN Index;
1032 EFI_USB_PORT_STATUS PortStatus;
1033
1034
1035 if (Usb2HcPpi != NULL) {
1036 MicroSecondDelay (200 * 1000);
1037
1038 //
1039 // reset root port
1040 //
1041 Status = Usb2HcPpi->SetRootHubPortFeature (
1042 PeiServices,
1043 Usb2HcPpi,
1044 PortNum,
1045 EfiUsbPortReset
1046 );
1047
1048 if (EFI_ERROR (Status)) {
1049 DEBUG ((DEBUG_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1050 return;
1051 }
1052
1053 //
1054 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1055 // section 7.1.7.5 for timing requirements.
1056 //
1057 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
1058
1059 //
1060 // clear reset root port
1061 //
1062 Status = Usb2HcPpi->ClearRootHubPortFeature (
1063 PeiServices,
1064 Usb2HcPpi,
1065 PortNum,
1066 EfiUsbPortReset
1067 );
1068
1069 if (EFI_ERROR (Status)) {
1070 DEBUG ((DEBUG_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1071 return;
1072 }
1073
1074 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
1075
1076 //
1077 // USB host controller won't clear the RESET bit until
1078 // reset is actually finished.
1079 //
1080 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
1081
1082 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1083 Status = Usb2HcPpi->GetRootHubPortStatus (
1084 PeiServices,
1085 Usb2HcPpi,
1086 PortNum,
1087 &PortStatus
1088 );
1089 if (EFI_ERROR (Status)) {
1090 return;
1091 }
1092
1093 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
1094 break;
1095 }
1096
1097 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
1098 }
1099
1100 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1101 DEBUG ((DEBUG_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
1102 return;
1103 }
1104
1105 Usb2HcPpi->ClearRootHubPortFeature (
1106 PeiServices,
1107 Usb2HcPpi,
1108 PortNum,
1109 EfiUsbPortResetChange
1110 );
1111
1112 Usb2HcPpi->ClearRootHubPortFeature (
1113 PeiServices,
1114 Usb2HcPpi,
1115 PortNum,
1116 EfiUsbPortConnectChange
1117 );
1118
1119 //
1120 // Set port enable
1121 //
1122 Usb2HcPpi->SetRootHubPortFeature(
1123 PeiServices,
1124 Usb2HcPpi,
1125 PortNum,
1126 EfiUsbPortEnable
1127 );
1128
1129 Usb2HcPpi->ClearRootHubPortFeature (
1130 PeiServices,
1131 Usb2HcPpi,
1132 PortNum,
1133 EfiUsbPortEnableChange
1134 );
1135
1136 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1137 } else {
1138 MicroSecondDelay (200 * 1000);
1139
1140 //
1141 // reset root port
1142 //
1143 Status = UsbHcPpi->SetRootHubPortFeature (
1144 PeiServices,
1145 UsbHcPpi,
1146 PortNum,
1147 EfiUsbPortReset
1148 );
1149
1150 if (EFI_ERROR (Status)) {
1151 DEBUG ((DEBUG_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1152 return;
1153 }
1154
1155 //
1156 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1157 // section 7.1.7.5 for timing requirements.
1158 //
1159 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
1160
1161 //
1162 // clear reset root port
1163 //
1164 Status = UsbHcPpi->ClearRootHubPortFeature (
1165 PeiServices,
1166 UsbHcPpi,
1167 PortNum,
1168 EfiUsbPortReset
1169 );
1170
1171 if (EFI_ERROR (Status)) {
1172 DEBUG ((DEBUG_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1173 return;
1174 }
1175
1176 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
1177
1178 //
1179 // USB host controller won't clear the RESET bit until
1180 // reset is actually finished.
1181 //
1182 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
1183
1184 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1185 Status = UsbHcPpi->GetRootHubPortStatus (
1186 PeiServices,
1187 UsbHcPpi,
1188 PortNum,
1189 &PortStatus
1190 );
1191 if (EFI_ERROR (Status)) {
1192 return;
1193 }
1194
1195 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
1196 break;
1197 }
1198
1199 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
1200 }
1201
1202 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1203 DEBUG ((DEBUG_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
1204 return;
1205 }
1206
1207 UsbHcPpi->ClearRootHubPortFeature (
1208 PeiServices,
1209 UsbHcPpi,
1210 PortNum,
1211 EfiUsbPortResetChange
1212 );
1213
1214 UsbHcPpi->ClearRootHubPortFeature (
1215 PeiServices,
1216 UsbHcPpi,
1217 PortNum,
1218 EfiUsbPortConnectChange
1219 );
1220
1221 //
1222 // Set port enable
1223 //
1224 UsbHcPpi->SetRootHubPortFeature(
1225 PeiServices,
1226 UsbHcPpi,
1227 PortNum,
1228 EfiUsbPortEnable
1229 );
1230
1231 UsbHcPpi->ClearRootHubPortFeature (
1232 PeiServices,
1233 UsbHcPpi,
1234 PortNum,
1235 EfiUsbPortEnableChange
1236 );
1237
1238 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1239 }
1240 return;
1241 }