+\r
+/**\r
+ Install Usb Bus Protocol on host controller, and start the Usb bus\r
+\r
+ @param This The USB bus driver binding instance\r
+ @param Controller The controller to check\r
+ @param RemainingDevicePath The remaining device patch\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the usb bus\r
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusBuildProtocol (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ USB_BUS *UsbBus;\r
+ USB_DEVICE *RootHub;\r
+ USB_INTERFACE *RootIf;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS Status2;\r
+\r
+ UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
+\r
+ if (UsbBus == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UsbBus->Signature = USB_BUS_SIGNATURE;\r
+ UsbBus->HostHandle = Controller;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &UsbBus->DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
+\r
+ gBS->FreePool (UsbBus);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
+ // This is for backward compatbility with EFI 1.x. In UEFI\r
+ // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
+ // and USB_HC because EHCI driver will install both protocols\r
+ // (for the same reason). If we don't consume both of them,\r
+ // the unconsumed one may be opened by others.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ (VOID **) &(UsbBus->Usb2Hc),\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ Status2 = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ (VOID **) &(UsbBus->UsbHc),\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
+\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto CLOSE_HC;\r
+ }\r
+\r
+ UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
+ UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
+\r
+ //\r
+ // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Controller,\r
+ &mUsbBusProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &UsbBus->BusId\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));\r
+ goto CLOSE_HC;\r
+ }\r
+\r
+ //\r
+ // Initial the wanted child device path list, and add first RemainingDevicePath\r
+ //\r
+ InitializeListHead (&UsbBus->WantedUsbIoDPList);\r
+ Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ //\r
+ // Create a fake usb device for root hub\r
+ //\r
+ RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
+\r
+ if (RootHub == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto UNINSTALL_USBBUS;\r
+ }\r
+\r
+ RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
+\r
+ if (RootIf == NULL) {\r
+ gBS->FreePool (RootHub);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FREE_ROOTHUB;\r
+ }\r
+\r
+ RootHub->Bus = UsbBus;\r
+ RootHub->NumOfInterface = 1;\r
+ RootHub->Interfaces[0] = RootIf;\r
+ RootIf->Signature = USB_INTERFACE_SIGNATURE;\r
+ RootIf->Device = RootHub;\r
+ RootIf->DevicePath = UsbBus->DevicePath;\r
+\r
+ Status = mUsbRootHubApi.Init (RootIf);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));\r
+ goto FREE_ROOTHUB;\r
+ }\r
+\r
+ UsbBus->Devices[0] = RootHub;\r
+\r
+ DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
+ return EFI_SUCCESS;\r
+\r
+FREE_ROOTHUB:\r
+ if (RootIf != NULL) {\r
+ gBS->FreePool (RootIf);\r
+ }\r
+ if (RootHub != NULL) {\r
+ gBS->FreePool (RootHub);\r
+ }\r
+\r
+UNINSTALL_USBBUS:\r
+ gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
+\r
+CLOSE_HC:\r
+ if (UsbBus->Usb2Hc != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+ if (UsbBus->UsbHc != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ gBS->FreePool (UsbBus);\r
+\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
+ return Status;\r
+}\r
+\r