3 This file implement the command set of "USB Mass Storage Specification
6 Copyright (c) 2007 - 2008, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
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.
17 #include "UsbMassImpl.h"
21 Return the current TPL.
33 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
34 gBS
->RestoreTPL (Tpl
);
40 Read an UINT32 from the buffer to avoid byte alignment problems, then
41 convert that to the little endia. The USB mass storage bootability spec
44 @param Buf The buffer contains the first byte of the UINT32
47 @return The UINT32 value read from the buffer in little endia.
57 CopyMem (&Value
, Buf
, sizeof (UINT32
));
58 return USB_BOOT_SWAP32 (Value
);
63 Put an UINT32 in little endia to the buffer. The data is converted to
64 big endia before writing.
66 @param Buf The buffer to write data to.
67 @param Data32 The data to write.
78 Data32
= USB_BOOT_SWAP32 (Data32
);
79 CopyMem (Buf
, &Data32
, sizeof (UINT32
));
83 Put an UINT16 in little endia to the buffer. The data is converted to
84 big endia before writing.
86 @param Buf The buffer to write data to.
87 @param Data16 The data to write.
98 Data16
= (UINT16
) (USB_BOOT_SWAP16 (Data16
));
99 CopyMem (Buf
, &Data16
, sizeof (UINT16
));
103 Request sense information via sending Request Sense
106 @param UsbMass The device to be requested sense data.
108 @retval EFI_SUCCESS The command is excuted OK.
109 @retval EFI_DEVICE_ERROR Failed to request sense.
110 @retval EFI_NO_RESPONSE The device media doesn't response this request.
111 @retval EFI_INVALID_PARAMETER The command has some invalid parameters.
112 @retval EFI_WRITE_PROTECTED The device is write protected.
113 @retval EFI_MEDIA_CHANGED The device media has been changed.
117 UsbBootRequestSense (
118 IN USB_MASS_DEVICE
*UsbMass
121 USB_BOOT_REQUEST_SENSE_CMD SenseCmd
;
122 USB_BOOT_REQUEST_SENSE_DATA SenseData
;
123 EFI_BLOCK_IO_MEDIA
*Media
;
124 USB_MASS_TRANSPORT
*Transport
;
128 Transport
= UsbMass
->Transport
;
131 // Request the sense data from the device if command failed
133 ZeroMem (&SenseCmd
, sizeof (USB_BOOT_REQUEST_SENSE_CMD
));
134 ZeroMem (&SenseData
, sizeof (USB_BOOT_REQUEST_SENSE_DATA
));
136 SenseCmd
.OpCode
= USB_BOOT_REQUEST_SENSE_OPCODE
;
137 SenseCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
138 SenseCmd
.AllocLen
= sizeof (USB_BOOT_REQUEST_SENSE_DATA
);
140 Status
= Transport
->ExecCommand (
143 sizeof (USB_BOOT_REQUEST_SENSE_CMD
),
146 sizeof (USB_BOOT_REQUEST_SENSE_DATA
),
148 USB_BOOT_GENERAL_CMD_TIMEOUT
,
151 if (EFI_ERROR (Status
) || CmdResult
!= USB_MASS_CMD_SUCCESS
) {
152 DEBUG ((EFI_D_ERROR
, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status
, CmdResult
));
157 // Interpret the sense data and update the media status if necessary.
159 Media
= &UsbMass
->BlockIoMedia
;
161 switch (USB_BOOT_SENSE_KEY (SenseData
.SenseKey
)) {
163 case USB_BOOT_SENSE_NO_SENSE
:
164 Status
= EFI_NO_RESPONSE
;
167 case USB_BOOT_SENSE_RECOVERED
:
169 // Suppose hardware can handle this case, and recover later by itself
171 Status
= EFI_NOT_READY
;
174 case USB_BOOT_SENSE_NOT_READY
:
175 Status
= EFI_DEVICE_ERROR
;
176 if (SenseData
.ASC
== USB_BOOT_ASC_NO_MEDIA
) {
177 Media
->MediaPresent
= FALSE
;
178 Status
= EFI_NO_MEDIA
;
179 } else if (SenseData
.ASC
== USB_BOOT_ASC_NOT_READY
) {
180 Status
= EFI_NOT_READY
;
184 case USB_BOOT_SENSE_ILLEGAL_REQUEST
:
185 Status
= EFI_INVALID_PARAMETER
;
188 case USB_BOOT_SENSE_UNIT_ATTENTION
:
189 Status
= EFI_DEVICE_ERROR
;
190 if (SenseData
.ASC
== USB_BOOT_ASC_MEDIA_CHANGE
) {
192 // If MediaChange, reset ReadOnly and new MediId
194 Status
= EFI_MEDIA_CHANGED
;
195 Media
->ReadOnly
= FALSE
;
200 case USB_BOOT_SNESE_DATA_PROTECT
:
201 Status
= EFI_WRITE_PROTECTED
;
202 Media
->ReadOnly
= TRUE
;
206 Status
= EFI_DEVICE_ERROR
;
210 DEBUG ((EFI_D_INFO
, "UsbBootRequestSense: (%r) with sense key %x/%x/%x\n",
212 USB_BOOT_SENSE_KEY (SenseData
.SenseKey
),
222 Execute the USB mass storage bootability commands. If execution
223 failed, retrieve the error by REQUEST_SENSE then update the device's
224 status, such as ReadyOnly.
226 @param UsbMass The device to issue commands to
227 @param Cmd The command to execute
228 @param CmdLen The length of the command
229 @param DataDir The direction of data transfer
230 @param Data The buffer to hold the data
231 @param DataLen The length of expected data
232 @param Timeout The timeout used to transfer
234 @retval EFI_SUCCESS The command is excuted OK
235 @retval EFI_DEVICE_ERROR Failed to request sense
236 @retval EFI_INVALID_PARAMETER The command has some invalid parameters
237 @retval EFI_WRITE_PROTECTED The device is write protected
238 @retval EFI_MEDIA_CHANGED The device media has been changed
243 IN USB_MASS_DEVICE
*UsbMass
,
246 IN EFI_USB_DATA_DIRECTION DataDir
,
252 USB_MASS_TRANSPORT
*Transport
;
256 Transport
= UsbMass
->Transport
;
257 Status
= Transport
->ExecCommand (
269 // ExecCommand return success and get the right CmdResult means
270 // the commnad transfer is OK.
272 if ((CmdResult
== USB_MASS_CMD_SUCCESS
) && !EFI_ERROR(Status
)) {
276 DEBUG ((EFI_D_INFO
, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
277 *(UINT8
*)Cmd
,Status
));
279 return UsbBootRequestSense (UsbMass
);
284 Execute the USB mass storage bootability commands. If execution
285 failed, retrieve the error by REQUEST_SENSE then update the device's
286 status, such as ReadyOnly.
288 @param UsbMass The device to issue commands to
289 @param Cmd The command to execute
290 @param CmdLen The length of the command
291 @param DataDir The direction of data transfer
292 @param Data The buffer to hold the data
293 @param DataLen The length of expected data
294 @param Timeout The timeout used to transfer
296 @retval EFI_SUCCESS The command is excuted OK
297 @retval EFI_DEVICE_ERROR Failed to request sense
298 @retval EFI_INVALID_PARAMETER The command has some invalid parameters
299 @retval EFI_WRITE_PROTECTED The device is write protected
300 @retval EFI_MEDIA_CHANGED The device media has been changed
304 UsbBootExecCmdWithRetry (
305 IN USB_MASS_DEVICE
*UsbMass
,
308 IN EFI_USB_DATA_DIRECTION DataDir
,
318 // If the device isn't ready, wait some time. If the device is ready,
319 // retry the command again.
321 Status
= EFI_SUCCESS
;
323 for (Index
= 0; Index
< USB_BOOT_COMMAND_RETRY
; Index
++) {
325 // Execute the command with an increasingly larger timeout value.
327 Status
= UsbBootExecCmd (
336 if (Status
== EFI_SUCCESS
||
337 Status
== EFI_MEDIA_CHANGED
) {
341 // Need retry once more, so reset index
343 if (Status
== EFI_NOT_READY
) {
353 Use the TEST UNIT READY command to check whether it is ready.
354 If it is ready, update the parameters.
356 @param UsbMass The device to test
358 @retval EFI_SUCCESS The device is ready and parameters are updated.
359 @retval Others Device not ready.
364 IN USB_MASS_DEVICE
*UsbMass
367 USB_BOOT_TEST_UNIT_READY_CMD TestCmd
;
369 ZeroMem (&TestCmd
, sizeof (USB_BOOT_TEST_UNIT_READY_CMD
));
371 TestCmd
.OpCode
= USB_BOOT_TEST_UNIT_READY_OPCODE
;
372 TestCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
374 return UsbBootExecCmdWithRetry (
377 sizeof (USB_BOOT_TEST_UNIT_READY_CMD
),
381 USB_BOOT_GENERAL_CMD_TIMEOUT
387 Inquiry Command requests that information regrarding parameters of
388 the Device be sent to the Host.
390 @param UsbMass The device to inquiry.
392 @retval EFI_SUCCESS The device is ready and parameters are updated.
393 @retval Others Device not ready.
398 IN USB_MASS_DEVICE
*UsbMass
401 USB_BOOT_INQUIRY_CMD InquiryCmd
;
402 USB_BOOT_INQUIRY_DATA InquiryData
;
403 EFI_BLOCK_IO_MEDIA
*Media
;
406 Media
= &(UsbMass
->BlockIoMedia
);
409 // Use the Inquiry command to get the RemovableMedia setting.
411 ZeroMem (&InquiryCmd
, sizeof (USB_BOOT_INQUIRY_CMD
));
412 ZeroMem (&InquiryData
, sizeof (USB_BOOT_INQUIRY_DATA
));
414 InquiryCmd
.OpCode
= USB_BOOT_INQUIRY_OPCODE
;
415 InquiryCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
416 InquiryCmd
.AllocLen
= sizeof (InquiryData
);
418 Status
= UsbBootExecCmdWithRetry (
421 sizeof (USB_BOOT_INQUIRY_CMD
),
424 sizeof (USB_BOOT_INQUIRY_DATA
),
425 USB_BOOT_GENERAL_CMD_TIMEOUT
427 if (EFI_ERROR (Status
)) {
431 UsbMass
->Pdt
= (UINT8
) (USB_BOOT_PDT (InquiryData
.Pdt
));
432 Media
->RemovableMedia
= (BOOLEAN
) (USB_BOOT_REMOVABLE (InquiryData
.Removable
));
434 // Default value 512 Bytes, in case no media present at first time
436 Media
->BlockSize
= 0x0200;
443 Get the capacity of the USB mass storage media, including
444 the presentation, block size, and last block number. This
445 function is used to get the disk parameters at the start if
446 it is a non-removable media or to detect the media if it is
449 @param UsbMass The device to retireve disk gemotric.
451 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
452 @retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
453 @retval Other Read capacity request fails.
457 UsbBootReadCapacity (
458 IN USB_MASS_DEVICE
*UsbMass
461 USB_BOOT_READ_CAPACITY_CMD CapacityCmd
;
462 USB_BOOT_READ_CAPACITY_DATA CapacityData
;
463 EFI_BLOCK_IO_MEDIA
*Media
;
466 Media
= &UsbMass
->BlockIoMedia
;
469 // Use the READ CAPACITY command to get the block length and last blockno
471 ZeroMem (&CapacityCmd
, sizeof (USB_BOOT_READ_CAPACITY_CMD
));
472 ZeroMem (&CapacityData
, sizeof (USB_BOOT_READ_CAPACITY_DATA
));
474 CapacityCmd
.OpCode
= USB_BOOT_READ_CAPACITY_OPCODE
;
475 CapacityCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
477 Status
= UsbBootExecCmdWithRetry (
480 sizeof (USB_BOOT_READ_CAPACITY_CMD
),
483 sizeof (USB_BOOT_READ_CAPACITY_DATA
),
484 USB_BOOT_GENERAL_CMD_TIMEOUT
486 if (EFI_ERROR (Status
)) {
490 Media
->MediaPresent
= TRUE
;
491 Media
->LastBlock
= UsbBootGetUint32 (CapacityData
.LastLba
);
492 Media
->BlockSize
= UsbBootGetUint32 (CapacityData
.BlockLen
);
494 if (Media
->BlockSize
== 0) {
495 return EFI_NOT_READY
;
498 DEBUG ((EFI_D_INFO
, "UsbBootReadCapacity Success LBA=%ld BlockSize=%d\n",
499 Media
->LastBlock
, Media
->BlockSize
));
505 Retrieves mode sense information via sending Mode Sense
508 @param UsbMass The USB_FLOPPY_DEV instance.
510 @retval EFI_SUCCESS Success
511 @retval Other Execute Request command fails.
516 IN USB_MASS_DEVICE
*UsbMass
520 USB_SCSI_MODE_SENSE6_CMD ModeSenseCmd
;
521 USB_SCSI_MODE_SENSE6_PARA_HEADER ModeParaHeader
;
522 EFI_BLOCK_IO_MEDIA
*Media
;
524 Media
= &UsbMass
->BlockIoMedia
;
526 ZeroMem (&ModeSenseCmd
, sizeof (USB_SCSI_MODE_SENSE6_CMD
));
527 ZeroMem (&ModeParaHeader
, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
));
530 // ModeSense6 command is defined in [SCSI2Spec-Page151]
532 ModeSenseCmd
.OpCode
= USB_SCSI_MODE_SENSE6_OPCODE
;
533 ModeSenseCmd
.Lun
= (UINT8
) USB_BOOT_LUN (UsbMass
->Lun
);
534 ModeSenseCmd
.PageCode
= 0x3F;
535 ModeSenseCmd
.AllocateLen
= (UINT8
) sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
);
537 Status
= UsbBootExecCmdWithRetry (
540 sizeof (USB_SCSI_MODE_SENSE6_CMD
),
543 sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER
),
544 USB_BOOT_GENERAL_CMD_TIMEOUT
548 // ModeSense(6) is used to get the information of WriteProtected. While only some of
549 // devices support this command, so have a try here.
551 if (!EFI_ERROR (Status
)) {
552 Media
->ReadOnly
= (BOOLEAN
) (((ModeParaHeader
.DevicePara
& 0x80) != 0) ? TRUE
: FALSE
);
560 Get the parameters for the USB mass storage media, including
561 the RemovableMedia, block size, and last block number. This
562 function is used both to initialize the media during the
563 DriverBindingStart and to re-initialize it when the media is
564 changed. Althought the RemoveableMedia is unlikely to change,
567 @param UsbMass The device to retireve disk gemotric.
569 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
570 @retval Other Get the parameters failed.
575 IN USB_MASS_DEVICE
*UsbMass
578 EFI_BLOCK_IO_MEDIA
*Media
;
582 Media
= &(UsbMass
->BlockIoMedia
);
583 CmdSet
= ((EFI_USB_INTERFACE_DESCRIPTOR
*) (UsbMass
->Context
))->InterfaceSubClass
;
585 Status
= UsbBootInquiry (UsbMass
);
586 if (EFI_ERROR (Status
)) {
587 DEBUG ((EFI_D_ERROR
, "UsbBootGetParams: UsbBootInquiry (%r)\n", Status
));
592 // Don't use the Removable bit in inquirydata to test whether the media
593 // is removable because many flash disks wrongly set this bit.
595 if ((UsbMass
->Pdt
== USB_PDT_CDROM
) || (UsbMass
->Pdt
== USB_PDT_OPTICAL
)) {
597 // CD-Rom device and Non-CD optical device
599 UsbMass
->OpticalStorage
= TRUE
;
601 // Default value 2048 Bytes, in case no media present at first time
603 Media
->BlockSize
= 0x0800;
606 if ((UsbMass
->Pdt
!= USB_PDT_CDROM
) && (CmdSet
== USB_MASS_STORE_SCSI
)) {
608 // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
609 // which is from [MassStorageBootabilitySpec-Page7].
610 // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
611 // could get the information of WriteProtected.
612 // Since not all device support this command, so skip if fail.
614 UsbScsiModeSense (UsbMass
);
617 return UsbBootReadCapacity (UsbMass
);
622 Detect whether the removable media is present and whether it has changed.
623 The Non-removable media doesn't need it.
625 @param UsbMass The device to retireve disk gemotric.
627 @retval EFI_SUCCESS The disk gemotric is successfully retrieved.
628 @retval Other Decect media fails.
633 IN USB_MASS_DEVICE
*UsbMass
636 EFI_BLOCK_IO_MEDIA OldMedia
;
637 EFI_BLOCK_IO_MEDIA
*Media
;
642 Media
= &UsbMass
->BlockIoMedia
;
646 &(UsbMass
->BlockIoMedia
),
647 sizeof (EFI_BLOCK_IO_MEDIA
)
650 CmdSet
= ((EFI_USB_INTERFACE_DESCRIPTOR
*) (UsbMass
->Context
))->InterfaceSubClass
;
652 Status
= UsbBootIsUnitReady (UsbMass
);
653 if (EFI_ERROR (Status
)) {
654 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status
));
658 if ((UsbMass
->Pdt
!= USB_PDT_CDROM
) && (CmdSet
== USB_MASS_STORE_SCSI
)) {
660 // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
661 // which is from [MassStorageBootabilitySpec-Page7].
662 // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
663 // could get the information of WriteProtected.
664 // Since not all device support this command, so skip if fail.
666 UsbScsiModeSense (UsbMass
);
669 Status
= UsbBootReadCapacity (UsbMass
);
670 if (EFI_ERROR (Status
)) {
671 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status
));
679 // Detect whether it is necessary to reinstall the BlockIO
681 // MediaId may change in RequestSense for MediaChanged
682 // MediaPresent may change in RequestSense for NoMedia
683 // MediaReadOnly may change in RequestSense for WriteProtected or MediaChanged
684 // MediaPresent/BlockSize/LastBlock may change in ReadCapacity
686 if ((Media
->MediaId
!= OldMedia
.MediaId
) ||
687 (Media
->MediaPresent
!= OldMedia
.MediaPresent
) ||
688 (Media
->ReadOnly
!= OldMedia
.ReadOnly
) ||
689 (Media
->BlockSize
!= OldMedia
.BlockSize
) ||
690 (Media
->LastBlock
!= OldMedia
.LastBlock
)) {
692 OldTpl
= UsbGetCurrentTpl ();
693 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: TPL before reinstall BlockIoProtocol is %d\n", OldTpl
));
695 gBS
->RestoreTPL (TPL_CALLBACK
);
697 gBS
->ReinstallProtocolInterface (
699 &gEfiBlockIoProtocolGuid
,
704 DEBUG ((EFI_D_ERROR
, "UsbBootDetectMedia: TPL after reinstall is %d\n", UsbGetCurrentTpl()));
705 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK
);
707 gBS
->RaiseTPL (OldTpl
);
710 // Update MediaId after reinstall BLOCK_IO_PROTOCOL
712 if (Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
713 if (Media
->MediaPresent
== TRUE
) {
720 if ((Media
->ReadOnly
!= OldMedia
.ReadOnly
) ||
721 (Media
->BlockSize
!= OldMedia
.BlockSize
) ||
722 (Media
->LastBlock
!= OldMedia
.LastBlock
)) {
732 Read some blocks from the device.
734 @param UsbMass The USB mass storage device to read from
735 @param Lba The start block number
736 @param TotalBlock Total block number to read
737 @param Buffer The buffer to read to
739 @retval EFI_SUCCESS Data are read into the buffer
740 @retval Others Failed to read all the data
745 IN USB_MASS_DEVICE
*UsbMass
,
751 USB_BOOT_READ10_CMD ReadCmd
;
758 BlockSize
= UsbMass
->BlockIoMedia
.BlockSize
;
759 Status
= EFI_SUCCESS
;
761 while (TotalBlock
> 0) {
763 // Split the total blocks into smaller pieces to ease the pressure
764 // on the device. We must split the total block because the READ10
765 // command only has 16 bit transfer length (in the unit of block).
767 Count
= (UINT16
)((TotalBlock
< USB_BOOT_IO_BLOCKS
) ? TotalBlock
: USB_BOOT_IO_BLOCKS
);
768 ByteSize
= (UINT32
)Count
* BlockSize
;
771 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
773 Timeout
= (UINT32
) USB_BOOT_GENERAL_CMD_TIMEOUT
;
776 // Fill in the command then execute
778 ZeroMem (&ReadCmd
, sizeof (USB_BOOT_READ10_CMD
));
780 ReadCmd
.OpCode
= USB_BOOT_READ10_OPCODE
;
781 ReadCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
782 UsbBootPutUint32 (ReadCmd
.Lba
, Lba
);
783 UsbBootPutUint16 (ReadCmd
.TransferLen
, Count
);
785 Status
= UsbBootExecCmdWithRetry (
788 sizeof (USB_BOOT_READ10_CMD
),
794 if (EFI_ERROR (Status
)) {
799 Buffer
+= Count
* BlockSize
;
808 Write some blocks to the device.
810 @param UsbMass The USB mass storage device to write to
811 @param Lba The start block number
812 @param TotalBlock Total block number to write
813 @param Buffer The buffer to write to
815 @retval EFI_SUCCESS Data are written into the buffer
816 @retval Others Failed to write all the data
821 IN USB_MASS_DEVICE
*UsbMass
,
827 USB_BOOT_WRITE10_CMD WriteCmd
;
834 BlockSize
= UsbMass
->BlockIoMedia
.BlockSize
;
835 Status
= EFI_SUCCESS
;
837 while (TotalBlock
> 0) {
839 // Split the total blocks into smaller pieces to ease the pressure
840 // on the device. We must split the total block because the WRITE10
841 // command only has 16 bit transfer length (in the unit of block).
843 Count
= (UINT16
)((TotalBlock
< USB_BOOT_IO_BLOCKS
) ? TotalBlock
: USB_BOOT_IO_BLOCKS
);
844 ByteSize
= (UINT32
)Count
* BlockSize
;
847 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
849 Timeout
= (UINT32
) USB_BOOT_GENERAL_CMD_TIMEOUT
;
852 // Fill in the write10 command block
854 ZeroMem (&WriteCmd
, sizeof (USB_BOOT_WRITE10_CMD
));
856 WriteCmd
.OpCode
= USB_BOOT_WRITE10_OPCODE
;
857 WriteCmd
.Lun
= (UINT8
) (USB_BOOT_LUN (UsbMass
->Lun
));
858 UsbBootPutUint32 (WriteCmd
.Lba
, Lba
);
859 UsbBootPutUint16 (WriteCmd
.TransferLen
, Count
);
861 Status
= UsbBootExecCmdWithRetry (
864 sizeof (USB_BOOT_WRITE10_CMD
),
870 if (EFI_ERROR (Status
)) {
875 Buffer
+= Count
* BlockSize
;
884 Use the USB clear feature control transfer to clear the endpoint
887 @param UsbIo The USB IO protocol to use
888 @param EndpointAddr The endpoint to clear stall for
890 @retval EFI_SUCCESS The endpoint stall condtion is clear
891 @retval Others Failed to clear the endpoint stall condtion
895 UsbClearEndpointStall (
896 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
897 IN UINT8 EndpointAddr
900 EFI_USB_DEVICE_REQUEST Request
;
905 Request
.RequestType
= 0x02;
906 Request
.Request
= USB_REQ_CLEAR_FEATURE
;
907 Request
.Value
= USB_FEATURE_ENDPOINT_HALT
;
908 Request
.Index
= EndpointAddr
;
910 Timeout
= USB_BOOT_GENERAL_CMD_TIMEOUT
/ USB_MASS_1_MILLISECOND
;
912 Status
= UsbIo
->UsbControlTransfer (