/** Scan EMMC Bus to discover the device. @param[in] Private The EMMC driver private data structure. @param[in] Slot The slot number to check device present. @param[in] RemainingDevicePath The pointer to the remaining device path. @retval EFI_SUCCESS Successfully to discover the device and attach SdMmcIoProtocol to it. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval EFI_ALREADY_STARTED The device was discovered before. @retval Others Fail to discover the device. **/ EFI_STATUS EFIAPI DiscoverEmmcDevice ( IN EMMC_DRIVER_PRIVATE_DATA *Private, IN UINT8 Slot, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EMMC_DEVICE *Device; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; EFI_DEVICE_PATH_PROTOCOL *RemainingEmmcDevPath; EFI_DEV_PATH *Node; EFI_HANDLE DeviceHandle; EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; UINT8 Index; Device = NULL; DevicePath = NULL; NewDevicePath = NULL; RemainingDevicePath = NULL; PassThru = Private->PassThru; Device = &Private->Device[Slot]; // // Build Device Path to check if the EMMC device present at the slot. // Status = PassThru->BuildDevicePath ( PassThru, Slot, &DevicePath ); if (EFI_ERROR(Status)) { return Status; } if (DevicePath->SubType != MSG_EMMC_DP) { Status = EFI_UNSUPPORTED; goto Error; } NewDevicePath = AppendDevicePathNode ( Private->ParentDevicePath, DevicePath ); if (NewDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } DeviceHandle = NULL; RemainingEmmcDevPath = NewDevicePath; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingEmmcDevPath, &DeviceHandle); // // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized. // if (EFI_ERROR (Status) || (DeviceHandle == NULL) || !IsDevicePathEnd (RemainingEmmcDevPath)) { Device->DevicePath = NewDevicePath; Device->Slot = Slot; Device->Private = Private; // // Expose user area in the Sd memory card to upper layer. // Status = DiscoverAllPartitions (Device); if (EFI_ERROR(Status)) { FreePool (NewDevicePath); goto Error; } Status = gBS->InstallProtocolInterface ( &Device->Handle, &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE, Device->DevicePath ); if (EFI_ERROR(Status)) { FreePool (NewDevicePath); goto Error; } Device->ControllerNameTable = NULL; GetEmmcModelName (Device, &Device->Cid); AddUnicodeString2 ( "eng", gEmmcDxeComponentName.SupportedLanguages, &Device->ControllerNameTable, Device->ModelName, TRUE ); AddUnicodeString2 ( "en", gEmmcDxeComponentName.SupportedLanguages, &Device->ControllerNameTable, Device->ModelName, FALSE ); } if (RemainingDevicePath == NULL) { // // Expose all partitions in the Emmc device to upper layer. // for (Index = 0; Index < EMMC_MAX_PARTITIONS; Index++) { InstallProtocolOnPartition (Device, Index); } } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // Enumerate the specified partition // Node = (EFI_DEV_PATH *) RemainingDevicePath; if ((DevicePathType (&Node->DevPath) != HARDWARE_DEVICE_PATH) || (DevicePathSubType (&Node->DevPath) != HW_CONTROLLER_DP) || (DevicePathNodeLength (&Node->DevPath) != sizeof (CONTROLLER_DEVICE_PATH))) { Status = EFI_INVALID_PARAMETER; goto Error; } Index = (UINT8)Node->Controller.ControllerNumber; if (Index >= EMMC_MAX_PARTITIONS) { Status = EFI_INVALID_PARAMETER; goto Error; } Status = InstallProtocolOnPartition (Device, Index); } Error: FreePool (DevicePath); return Status; }
/** Scan SD Bus to discover the device. @param[in] Private The SD driver private data structure. @param[in] Slot The slot number to check device present. @retval EFI_SUCCESS Successfully to discover the device and attach SdMmcIoProtocol to it. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval EFI_ALREADY_STARTED The device was discovered before. @retval Others Fail to discover the device. **/ EFI_STATUS EFIAPI DiscoverSdDevice ( IN SD_DRIVER_PRIVATE_DATA *Private, IN UINT8 Slot ) { EFI_STATUS Status; SD_DEVICE *Device; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_HANDLE DeviceHandle; EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; Device = NULL; DevicePath = NULL; NewDevicePath = NULL; RemainingDevicePath = NULL; PassThru = Private->PassThru; // // Build Device Path // Status = PassThru->BuildDevicePath ( PassThru, Slot, &DevicePath ); if (EFI_ERROR(Status)) { return Status; } if (DevicePath->SubType != MSG_SD_DP) { Status = EFI_UNSUPPORTED; goto Error; } NewDevicePath = AppendDevicePathNode ( Private->ParentDevicePath, DevicePath ); if (NewDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } DeviceHandle = NULL; RemainingDevicePath = NewDevicePath; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle); if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) { // // The device has been started, directly return to fast boot. // Status = EFI_ALREADY_STARTED; goto Error; } // // Allocate buffer to store SD_DEVICE private data. // Device = AllocateCopyPool (sizeof (SD_DEVICE), &mSdDeviceTemplate); if (Device == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } Device->DevicePath = NewDevicePath; Device->Slot = Slot; Device->Private = Private; InitializeListHead (&Device->Queue); // // Expose user area in the Sd memory card to upper layer. // Status = DiscoverUserArea (Device); if (EFI_ERROR(Status)) { goto Error; } Device->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gSdDxeComponentName.SupportedLanguages, &Device->ControllerNameTable, Device->ModelName, TRUE ); AddUnicodeString2 ( "en", gSdDxeComponentName2.SupportedLanguages, &Device->ControllerNameTable, Device->ModelName, FALSE ); Status = gBS->InstallMultipleProtocolInterfaces ( &Device->Handle, &gEfiDevicePathProtocolGuid, Device->DevicePath, &gEfiBlockIoProtocolGuid, &Device->BlockIo, &gEfiBlockIo2ProtocolGuid, &Device->BlockIo2, &gEfiEraseBlockProtocolGuid, &Device->EraseBlock, &gEfiDiskInfoProtocolGuid, &Device->DiskInfo, NULL ); if (!EFI_ERROR (Status)) { gBS->OpenProtocol ( Private->Controller, &gEfiSdMmcPassThruProtocolGuid, (VOID **) &(Private->PassThru), Private->DriverBindingHandle, Device->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } Error: FreePool (DevicePath); if (EFI_ERROR (Status) && (NewDevicePath != NULL)) { FreePool (NewDevicePath); } if (EFI_ERROR (Status) && (Device != NULL)) { FreePool (Device); } return Status; }