TianoCore EDK2 master
Loading...
Searching...
No Matches
UsbMassBoot.c
Go to the documentation of this file.
1
10#include "UsbMass.h"
11
27 IN USB_MASS_DEVICE *UsbMass
28 )
29{
32 EFI_BLOCK_IO_MEDIA *Media;
33 USB_MASS_TRANSPORT *Transport;
34 EFI_STATUS Status;
35 UINT32 CmdResult;
36
37 Transport = UsbMass->Transport;
38
39 //
40 // Request the sense data from the device
41 //
42 ZeroMem (&SenseCmd, sizeof (USB_BOOT_REQUEST_SENSE_CMD));
43 ZeroMem (&SenseData, sizeof (USB_BOOT_REQUEST_SENSE_DATA));
44
45 SenseCmd.OpCode = USB_BOOT_REQUEST_SENSE_OPCODE;
46 SenseCmd.Lun = (UINT8)(USB_BOOT_LUN (UsbMass->Lun));
47 SenseCmd.AllocLen = (UINT8)sizeof (USB_BOOT_REQUEST_SENSE_DATA);
48
49 Status = Transport->ExecCommand (
50 UsbMass->Context,
51 &SenseCmd,
53 EfiUsbDataIn,
54 &SenseData,
56 UsbMass->Lun,
57 USB_BOOT_GENERAL_CMD_TIMEOUT,
58 &CmdResult
59 );
60 if (EFI_ERROR (Status) || (CmdResult != USB_MASS_CMD_SUCCESS)) {
61 DEBUG ((DEBUG_ERROR, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status, CmdResult));
62 if (!EFI_ERROR (Status)) {
63 Status = EFI_DEVICE_ERROR;
64 }
65
66 return Status;
67 }
68
69 //
70 // If sense data is retrieved successfully, interpret the sense data
71 // and update the media status if necessary.
72 //
73 Media = &UsbMass->BlockIoMedia;
74
75 switch (USB_BOOT_SENSE_KEY (SenseData.SenseKey)) {
77 if (SenseData.Asc == USB_BOOT_ASC_NO_ADDITIONAL_SENSE_INFORMATION) {
78 //
79 // It is not an error if a device does not have additional sense information
80 //
81 Status = EFI_SUCCESS;
82 } else {
83 Status = EFI_NO_RESPONSE;
84 }
85
86 break;
87
89 //
90 // Suppose hardware can handle this case, and recover later by itself
91 //
92 Status = EFI_NOT_READY;
93 break;
94
96 Status = EFI_DEVICE_ERROR;
97 if (SenseData.Asc == USB_BOOT_ASC_NO_MEDIA) {
98 Media->MediaPresent = FALSE;
99 Status = EFI_NO_MEDIA;
100 } else if (SenseData.Asc == USB_BOOT_ASC_NOT_READY) {
101 Status = EFI_NOT_READY;
102 }
103
104 break;
105
107 Status = EFI_INVALID_PARAMETER;
108 break;
109
111 Status = EFI_DEVICE_ERROR;
112 if (SenseData.Asc == USB_BOOT_ASC_MEDIA_CHANGE) {
113 //
114 // If MediaChange, reset ReadOnly and new MediaId
115 //
116 Status = EFI_MEDIA_CHANGED;
117 Media->ReadOnly = FALSE;
118 Media->MediaId++;
119 } else if (SenseData.Asc == USB_BOOT_ASC_NOT_READY) {
120 Status = EFI_NOT_READY;
121 } else if (SenseData.Asc == USB_BOOT_ASC_NO_MEDIA) {
122 Status = EFI_NOT_READY;
123 }
124
125 break;
126
128 Status = EFI_WRITE_PROTECTED;
129 Media->ReadOnly = TRUE;
130 break;
131
132 default:
133 Status = EFI_DEVICE_ERROR;
134 break;
135 }
136
137 DEBUG ((
138 DEBUG_INFO,
139 "UsbBootRequestSense: (%r) with error code (%x) sense key %x/%x/%x\n",
140 Status,
141 SenseData.ErrorCode,
142 USB_BOOT_SENSE_KEY (SenseData.SenseKey),
143 SenseData.Asc,
144 SenseData.Ascq
145 ));
146
147 return Status;
148}
149
171 IN USB_MASS_DEVICE *UsbMass,
172 IN VOID *Cmd,
173 IN UINT8 CmdLen,
175 IN VOID *Data,
176 IN UINT32 DataLen,
177 IN UINT32 Timeout
178 )
179{
180 USB_MASS_TRANSPORT *Transport;
181 EFI_STATUS Status;
182 UINT32 CmdResult;
183
184 Transport = UsbMass->Transport;
185 Status = Transport->ExecCommand (
186 UsbMass->Context,
187 Cmd,
188 CmdLen,
189 DataDir,
190 Data,
191 DataLen,
192 UsbMass->Lun,
193 Timeout,
194 &CmdResult
195 );
196
197 if (Status == EFI_TIMEOUT) {
198 DEBUG ((DEBUG_ERROR, "UsbBootExecCmd: %r to Exec 0x%x Cmd\n", Status, *(UINT8 *)Cmd));
199 return EFI_TIMEOUT;
200 }
201
202 //
203 // If ExecCommand() returns no error and CmdResult is success,
204 // then the command transfer is successful.
205 //
206 if ((CmdResult == USB_MASS_CMD_SUCCESS) && !EFI_ERROR (Status)) {
207 return EFI_SUCCESS;
208 }
209
210 //
211 // If command execution failed, then retrieve error info via sense request.
212 //
213 DEBUG ((DEBUG_ERROR, "UsbBootExecCmd: %r to Exec 0x%x Cmd (Result = %x)\n", Status, *(UINT8 *)Cmd, CmdResult));
214 return UsbBootRequestSense (UsbMass);
215}
216
240 IN USB_MASS_DEVICE *UsbMass,
241 IN VOID *Cmd,
242 IN UINT8 CmdLen,
244 IN VOID *Data,
245 IN UINT32 DataLen,
246 IN UINT32 Timeout
247 )
248{
249 EFI_STATUS Status;
250 UINTN Retry;
251 EFI_EVENT TimeoutEvt;
252
253 Retry = 0;
254 Status = EFI_SUCCESS;
255 Status = gBS->CreateEvent (
256 EVT_TIMER,
257 TPL_CALLBACK,
258 NULL,
259 NULL,
260 &TimeoutEvt
261 );
262 if (EFI_ERROR (Status)) {
263 return Status;
264 }
265
266 Status = gBS->SetTimer (TimeoutEvt, TimerRelative, EFI_TIMER_PERIOD_SECONDS (60));
267 if (EFI_ERROR (Status)) {
268 goto EXIT;
269 }
270
271 //
272 // Execute the cmd and retry if it fails.
273 //
274 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvt))) {
275 Status = UsbBootExecCmd (
276 UsbMass,
277 Cmd,
278 CmdLen,
279 DataDir,
280 Data,
281 DataLen,
282 Timeout
283 );
284 if ((Status == EFI_SUCCESS) || (Status == EFI_NO_MEDIA)) {
285 break;
286 }
287
288 //
289 // If the sense data shows the drive is not ready, we need execute the cmd again.
290 // We limit the upper boundary to 60 seconds.
291 //
292 if (Status == EFI_NOT_READY) {
293 continue;
294 }
295
296 //
297 // If the status is other error, then just retry 5 times.
298 //
299 if (Retry++ >= USB_BOOT_COMMAND_RETRY) {
300 break;
301 }
302 }
303
304EXIT:
305 if (TimeoutEvt != NULL) {
306 gBS->CloseEvent (TimeoutEvt);
307 }
308
309 return Status;
310}
311
323 IN USB_MASS_DEVICE *UsbMass
324 )
325{
327
328 ZeroMem (&TestCmd, sizeof (USB_BOOT_TEST_UNIT_READY_CMD));
329
330 TestCmd.OpCode = USB_BOOT_TEST_UNIT_READY_OPCODE;
331 TestCmd.Lun = (UINT8)(USB_BOOT_LUN (UsbMass->Lun));
332
334 UsbMass,
335 &TestCmd,
336 (UINT8)sizeof (USB_BOOT_TEST_UNIT_READY_CMD),
337 EfiUsbNoData,
338 NULL,
339 0,
340 USB_BOOT_GENERAL_CMD_TIMEOUT
341 );
342}
343
356 IN USB_MASS_DEVICE *UsbMass
357 )
358{
359 USB_BOOT_INQUIRY_CMD InquiryCmd;
360 EFI_BLOCK_IO_MEDIA *Media;
361 EFI_STATUS Status;
362
363 Media = &(UsbMass->BlockIoMedia);
364
365 ZeroMem (&InquiryCmd, sizeof (USB_BOOT_INQUIRY_CMD));
366 ZeroMem (&UsbMass->InquiryData, sizeof (USB_BOOT_INQUIRY_DATA));
367
368 InquiryCmd.OpCode = USB_BOOT_INQUIRY_OPCODE;
369 InquiryCmd.Lun = (UINT8)(USB_BOOT_LUN (UsbMass->Lun));
370 InquiryCmd.AllocLen = (UINT8)sizeof (USB_BOOT_INQUIRY_DATA);
371
372 Status = UsbBootExecCmdWithRetry (
373 UsbMass,
374 &InquiryCmd,
375 (UINT8)sizeof (USB_BOOT_INQUIRY_CMD),
376 EfiUsbDataIn,
377 &UsbMass->InquiryData,
378 sizeof (USB_BOOT_INQUIRY_DATA),
379 USB_BOOT_GENERAL_CMD_TIMEOUT
380 );
381 if (EFI_ERROR (Status)) {
382 return Status;
383 }
384
385 //
386 // Get information from PDT (Peripheral Device Type) field and Removable Medium Bit
387 // from the inquiry data.
388 //
389 UsbMass->Pdt = (UINT8)(USB_BOOT_PDT (UsbMass->InquiryData.Pdt));
390 Media->RemovableMedia = (BOOLEAN)(USB_BOOT_REMOVABLE (UsbMass->InquiryData.Removable));
391 //
392 // Set block size to the default value of 512 Bytes, in case no media is present at first time.
393 //
394 Media->BlockSize = 0x0200;
395
396 return Status;
397}
398
416 IN USB_MASS_DEVICE *UsbMass
417 )
418{
419 UINT8 CapacityCmd[16];
421 EFI_BLOCK_IO_MEDIA *Media;
422 EFI_STATUS Status;
423 UINT32 BlockSize;
424
425 Media = &UsbMass->BlockIoMedia;
426
427 Media->MediaPresent = FALSE;
428 Media->LastBlock = 0;
429 Media->BlockSize = 0;
430
431 ZeroMem (CapacityCmd, sizeof (CapacityCmd));
432 ZeroMem (&CapacityData, sizeof (CapacityData));
433
434 CapacityCmd[0] = EFI_SCSI_OP_READ_CAPACITY16;
435 CapacityCmd[1] = 0x10;
436 //
437 // Partial medium indicator, set the bytes 2 ~ 9 of the Cdb as ZERO.
438 //
439 ZeroMem ((CapacityCmd + 2), 8);
440
441 CapacityCmd[13] = sizeof (CapacityData);
442
443 Status = UsbBootExecCmdWithRetry (
444 UsbMass,
445 CapacityCmd,
446 (UINT8)sizeof (CapacityCmd),
447 EfiUsbDataIn,
448 &CapacityData,
449 sizeof (CapacityData),
450 USB_BOOT_GENERAL_CMD_TIMEOUT
451 );
452 if (EFI_ERROR (Status)) {
453 return Status;
454 }
455
456 //
457 // Get the information on media presence, block size, and last block number
458 // from READ CAPACITY data.
459 //
460 Media->MediaPresent = TRUE;
461 Media->LastBlock = SwapBytes64 (ReadUnaligned64 ((CONST UINT64 *)&(CapacityData.LastLba7)));
462
463 BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *)&(CapacityData.BlockSize3)));
464
465 Media->LowestAlignedLba = (CapacityData.LowestAlignLogic2 << 8) |
466 CapacityData.LowestAlignLogic1;
467 Media->LogicalBlocksPerPhysicalBlock = (1 << CapacityData.LogicPerPhysical);
468 if (BlockSize == 0) {
469 //
470 // Get sense data
471 //
472 return UsbBootRequestSense (UsbMass);
473 } else {
474 Media->BlockSize = BlockSize;
475 }
476
477 return Status;
478}
479
497 IN USB_MASS_DEVICE *UsbMass
498 )
499{
500 USB_BOOT_READ_CAPACITY_CMD CapacityCmd;
501 USB_BOOT_READ_CAPACITY_DATA CapacityData;
502 EFI_BLOCK_IO_MEDIA *Media;
503 EFI_STATUS Status;
504 UINT32 BlockSize;
505
506 Media = &UsbMass->BlockIoMedia;
507
508 ZeroMem (&CapacityCmd, sizeof (USB_BOOT_READ_CAPACITY_CMD));
509 ZeroMem (&CapacityData, sizeof (USB_BOOT_READ_CAPACITY_DATA));
510
511 CapacityCmd.OpCode = USB_BOOT_READ_CAPACITY_OPCODE;
512 CapacityCmd.Lun = (UINT8)(USB_BOOT_LUN (UsbMass->Lun));
513
514 Status = UsbBootExecCmdWithRetry (
515 UsbMass,
516 &CapacityCmd,
517 (UINT8)sizeof (USB_BOOT_READ_CAPACITY_CMD),
518 EfiUsbDataIn,
519 &CapacityData,
521 USB_BOOT_GENERAL_CMD_TIMEOUT
522 );
523 if (EFI_ERROR (Status)) {
524 return Status;
525 }
526
527 //
528 // Get the information on media presence, block size, and last block number
529 // from READ CAPACITY data.
530 //
531 Media->MediaPresent = TRUE;
532 Media->LastBlock = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *)CapacityData.LastLba));
533
534 BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *)CapacityData.BlockLen));
535 if (BlockSize == 0) {
536 //
537 // Get sense data
538 //
539 return UsbBootRequestSense (UsbMass);
540 } else {
541 Media->BlockSize = BlockSize;
542 }
543
544 if (Media->LastBlock == 0xFFFFFFFF) {
545 Status = UsbBootReadCapacity16 (UsbMass);
546 if (!EFI_ERROR (Status)) {
547 UsbMass->Cdb16Byte = TRUE;
548 }
549 }
550
551 return Status;
552}
553
565 IN USB_MASS_DEVICE *UsbMass
566 )
567{
568 EFI_STATUS Status;
569 USB_SCSI_MODE_SENSE6_CMD ModeSenseCmd;
571 EFI_BLOCK_IO_MEDIA *Media;
572
573 Media = &UsbMass->BlockIoMedia;
574
575 ZeroMem (&ModeSenseCmd, sizeof (USB_SCSI_MODE_SENSE6_CMD));
576 ZeroMem (&ModeParaHeader, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER));
577
578 //
579 // MODE SENSE(6) command is defined in Section 8.2.10 of SCSI-2 Spec
580 //
581 ModeSenseCmd.OpCode = USB_SCSI_MODE_SENSE6_OPCODE;
582 ModeSenseCmd.Lun = (UINT8)USB_BOOT_LUN (UsbMass->Lun);
583 ModeSenseCmd.PageCode = 0x3F;
584 ModeSenseCmd.AllocateLen = (UINT8)sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER);
585
586 Status = UsbBootExecCmdWithRetry (
587 UsbMass,
588 &ModeSenseCmd,
589 (UINT8)sizeof (USB_SCSI_MODE_SENSE6_CMD),
590 EfiUsbDataIn,
591 &ModeParaHeader,
593 USB_BOOT_GENERAL_CMD_TIMEOUT
594 );
595
596 //
597 // Format of device-specific parameter byte of the mode parameter header is defined in
598 // Section 8.2.10 of SCSI-2 Spec.
599 // BIT7 of this byte is indicates whether the medium is write protected.
600 //
601 if (!EFI_ERROR (Status)) {
602 Media->ReadOnly = (BOOLEAN)((ModeParaHeader.DevicePara & BIT7) != 0);
603 }
604
605 return Status;
606}
607
625 IN USB_MASS_DEVICE *UsbMass
626 )
627{
628 EFI_BLOCK_IO_MEDIA *Media;
629 EFI_STATUS Status;
630
631 Media = &(UsbMass->BlockIoMedia);
632
633 Status = UsbBootInquiry (UsbMass);
634 if (EFI_ERROR (Status)) {
635 DEBUG ((DEBUG_ERROR, "UsbBootGetParams: UsbBootInquiry (%r)\n", Status));
636 return Status;
637 }
638
639 //
640 // According to USB Mass Storage Specification for Bootability, only following
641 // 4 Peripheral Device Types are in spec.
642 //
643 if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) &&
644 (UsbMass->Pdt != USB_PDT_CDROM) &&
645 (UsbMass->Pdt != USB_PDT_OPTICAL) &&
646 (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT))
647 {
648 DEBUG ((DEBUG_ERROR, "UsbBootGetParams: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));
649 return EFI_UNSUPPORTED;
650 }
651
652 //
653 // Don't use the Removable bit in inquiry data to test whether the media
654 // is removable because many flash disks wrongly set this bit.
655 //
656 if ((UsbMass->Pdt == USB_PDT_CDROM) || (UsbMass->Pdt == USB_PDT_OPTICAL)) {
657 //
658 // CD-Rom device and Non-CD optical device
659 //
660 UsbMass->OpticalStorage = TRUE;
661 //
662 // Default value 2048 Bytes, in case no media present at first time
663 //
664 Media->BlockSize = 0x0800;
665 }
666
667 Status = UsbBootDetectMedia (UsbMass);
668
669 return Status;
670}
671
683 IN USB_MASS_DEVICE *UsbMass
684 )
685{
686 EFI_BLOCK_IO_MEDIA OldMedia;
687 EFI_BLOCK_IO_MEDIA *Media;
688 UINT8 CmdSet;
689 EFI_STATUS Status;
690
691 Media = &UsbMass->BlockIoMedia;
692
693 CopyMem (&OldMedia, &(UsbMass->BlockIoMedia), sizeof (EFI_BLOCK_IO_MEDIA));
694
695 CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *)(UsbMass->Context))->InterfaceSubClass;
696
697 Status = UsbBootIsUnitReady (UsbMass);
698 if (EFI_ERROR (Status)) {
699 DEBUG ((DEBUG_ERROR, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status));
700 }
701
702 //
703 // Status could be:
704 // EFI_SUCCESS: all good.
705 // EFI_NO_MEDIA: media is not present.
706 // others: HW error.
707 // For either EFI_NO_MEDIA, or HW error, skip to get WriteProtected and capacity information.
708 //
709 if (!EFI_ERROR (Status)) {
710 if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {
711 //
712 // MODE SENSE is required for the device with PDT of 0x00/0x07/0x0E,
713 // according to Section 4 of USB Mass Storage Specification for Bootability.
714 // MODE SENSE(10) is useless here, while MODE SENSE(6) defined in SCSI
715 // could get the information of Write Protected.
716 // Since not all device support this command, skip if fail.
717 //
718 UsbScsiModeSense (UsbMass);
719 }
720
721 Status = UsbBootReadCapacity (UsbMass);
722 if (EFI_ERROR (Status)) {
723 DEBUG ((DEBUG_ERROR, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status));
724 }
725 }
726
727 if (EFI_ERROR (Status) && (Status != EFI_NO_MEDIA)) {
728 //
729 // For NoMedia, BlockIo is still needed.
730 //
731 return Status;
732 }
733
734 //
735 // Simply reject device whose block size is unacceptable small (==0) or large (>64K).
736 //
737 if ((Media->BlockSize == 0) || (Media->BlockSize > USB_BOOT_MAX_CARRY_SIZE)) {
738 return EFI_DEVICE_ERROR;
739 }
740
741 //
742 // Detect whether it is necessary to reinstall the Block I/O Protocol.
743 //
744 // MediaId may change in RequestSense for MediaChanged
745 // MediaPresent may change in RequestSense for NoMedia
746 // MediaReadOnly may change in RequestSense for WriteProtected or MediaChanged
747 // MediaPresent/BlockSize/LastBlock may change in ReadCapacity
748 //
749 if ((Media->MediaId != OldMedia.MediaId) ||
750 (Media->MediaPresent != OldMedia.MediaPresent) ||
751 (Media->ReadOnly != OldMedia.ReadOnly) ||
752 (Media->BlockSize != OldMedia.BlockSize) ||
753 (Media->LastBlock != OldMedia.LastBlock))
754 {
755 //
756 // This function is called from:
757 // Block I/O Protocol APIs, which run at TPL_CALLBACK.
758 // DriverBindingStart(), which raises to TPL_CALLBACK.
759 ASSERT (EfiGetCurrentTpl () == TPL_CALLBACK);
760
761 //
762 // When it is called from DriverBindingStart(), below reinstall fails.
763 // So ignore the return status check.
764 //
765 gBS->ReinstallProtocolInterface (
766 UsbMass->Controller,
767 &gEfiBlockIoProtocolGuid,
768 &UsbMass->BlockIo,
769 &UsbMass->BlockIo
770 );
771
772 //
773 // Reset MediaId after reinstalling Block I/O Protocol.
774 //
775 if (Media->MediaPresent != OldMedia.MediaPresent) {
776 if (Media->MediaPresent) {
777 Media->MediaId = 1;
778 } else {
779 Media->MediaId = 0;
780 }
781 }
782
783 if ((Media->ReadOnly != OldMedia.ReadOnly) ||
784 (Media->BlockSize != OldMedia.BlockSize) ||
785 (Media->LastBlock != OldMedia.LastBlock))
786 {
787 Media->MediaId++;
788 }
789
790 Status = Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA;
791 }
792
793 return Status;
794}
795
811 IN USB_MASS_DEVICE *UsbMass,
812 IN BOOLEAN Write,
813 IN UINT32 Lba,
814 IN UINTN TotalBlock,
815 IN OUT UINT8 *Buffer
816 )
817{
819 EFI_STATUS Status;
820 UINT32 Count;
821 UINT32 CountMax;
822 UINT32 BlockSize;
823 UINT32 ByteSize;
824 UINT32 Timeout;
825
826 BlockSize = UsbMass->BlockIoMedia.BlockSize;
827 CountMax = USB_BOOT_MAX_CARRY_SIZE / BlockSize;
828 Status = EFI_SUCCESS;
829
830 while (TotalBlock > 0) {
831 //
832 // Split the total blocks into smaller pieces to ease the pressure
833 // on the device. We must split the total block because the READ10
834 // command only has 16 bit transfer length (in the unit of block).
835 //
836 Count = (UINT32)MIN (TotalBlock, CountMax);
837 Count = MIN (MAX_UINT16, Count);
838 ByteSize = Count * BlockSize;
839
840 //
841 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
842 //
843 Timeout = (UINT32)USB_BOOT_GENERAL_CMD_TIMEOUT;
844
845 //
846 // Fill in the command then execute
847 //
848 ZeroMem (&Cmd, sizeof (USB_BOOT_READ_WRITE_10_CMD));
849
850 Cmd.OpCode = Write ? USB_BOOT_WRITE10_OPCODE : USB_BOOT_READ10_OPCODE;
851 Cmd.Lun = (UINT8)(USB_BOOT_LUN (UsbMass->Lun));
852 WriteUnaligned32 ((UINT32 *)Cmd.Lba, SwapBytes32 (Lba));
853 WriteUnaligned16 ((UINT16 *)Cmd.TransferLen, SwapBytes16 ((UINT16)Count));
854
855 Status = UsbBootExecCmdWithRetry (
856 UsbMass,
857 &Cmd,
858 (UINT8)sizeof (USB_BOOT_READ_WRITE_10_CMD),
859 Write ? EfiUsbDataOut : EfiUsbDataIn,
860 Buffer,
861 ByteSize,
862 Timeout
863 );
864 if (EFI_ERROR (Status)) {
865 return Status;
866 }
867
868 DEBUG ((
869 DEBUG_BLKIO,
870 "UsbBoot%sBlocks: LBA (0x%lx), Blk (0x%x)\n",
871 Write ? L"Write" : L"Read",
872 Lba,
873 Count
874 ));
875 Lba += Count;
876 Buffer += ByteSize;
877 TotalBlock -= Count;
878 }
879
880 return Status;
881}
882
897 IN USB_MASS_DEVICE *UsbMass,
898 IN BOOLEAN Write,
899 IN UINT64 Lba,
900 IN UINTN TotalBlock,
901 IN OUT UINT8 *Buffer
902 )
903{
904 UINT8 Cmd[16];
905 EFI_STATUS Status;
906 UINT32 Count;
907 UINT32 CountMax;
908 UINT32 BlockSize;
909 UINT32 ByteSize;
910 UINT32 Timeout;
911
912 BlockSize = UsbMass->BlockIoMedia.BlockSize;
913 CountMax = USB_BOOT_MAX_CARRY_SIZE / BlockSize;
914 Status = EFI_SUCCESS;
915
916 while (TotalBlock > 0) {
917 //
918 // Split the total blocks into smaller pieces.
919 //
920 Count = (UINT32)MIN (TotalBlock, CountMax);
921 ByteSize = Count * BlockSize;
922
923 //
924 // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
925 //
926 Timeout = (UINT32)USB_BOOT_GENERAL_CMD_TIMEOUT;
927
928 //
929 // Fill in the command then execute
930 //
931 ZeroMem (Cmd, sizeof (Cmd));
932
933 Cmd[0] = Write ? EFI_SCSI_OP_WRITE16 : EFI_SCSI_OP_READ16;
934 Cmd[1] = (UINT8)((USB_BOOT_LUN (UsbMass->Lun) & 0xE0));
935 WriteUnaligned64 ((UINT64 *)&Cmd[2], SwapBytes64 (Lba));
936 WriteUnaligned32 ((UINT32 *)&Cmd[10], SwapBytes32 (Count));
937
938 Status = UsbBootExecCmdWithRetry (
939 UsbMass,
940 Cmd,
941 (UINT8)sizeof (Cmd),
942 Write ? EfiUsbDataOut : EfiUsbDataIn,
943 Buffer,
944 ByteSize,
945 Timeout
946 );
947 if (EFI_ERROR (Status)) {
948 return Status;
949 }
950
951 DEBUG ((
952 DEBUG_BLKIO,
953 "UsbBoot%sBlocks16: LBA (0x%lx), Blk (0x%x)\n",
954 Write ? L"Write" : L"Read",
955 Lba,
956 Count
957 ));
958 Lba += Count;
959 Buffer += ByteSize;
960 TotalBlock -= Count;
961 }
962
963 return Status;
964}
965
978 IN EFI_USB_IO_PROTOCOL *UsbIo,
979 IN UINT8 EndpointAddr
980 )
981{
983 EFI_STATUS Status;
984 UINT32 CmdResult;
985 UINT32 Timeout;
986
987 Request.RequestType = 0x02;
988 Request.Request = USB_REQ_CLEAR_FEATURE;
989 Request.Value = USB_FEATURE_ENDPOINT_HALT;
990 Request.Index = EndpointAddr;
991 Request.Length = 0;
992 Timeout = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_1_MILLISECOND;
993
994 Status = UsbIo->UsbControlTransfer (
995 UsbIo,
996 &Request,
997 EfiUsbNoData,
998 Timeout,
999 NULL,
1000 0,
1001 &CmdResult
1002 );
1003
1004 return Status;
1005}
UINT64 UINTN
UINT16 EFIAPI SwapBytes16(IN UINT16 Value)
Definition: SwapBytes16.c:25
UINT64 EFIAPI ReadUnaligned64(IN CONST UINT64 *Buffer)
Definition: Unaligned.c:204
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
Definition: Unaligned.c:177
UINT16 EFIAPI WriteUnaligned16(OUT UINT16 *Buffer, IN UINT16 Value)
Definition: Unaligned.c:61
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
UINT64 EFIAPI WriteUnaligned64(OUT UINT64 *Buffer, IN UINT64 Value)
Definition: Unaligned.c:236
UINT32 EFIAPI ReadUnaligned32(IN CONST UINT32 *Buffer)
Definition: Unaligned.c:145
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_USB_DATA_DIRECTION
Definition: UsbIo.h:44
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_TPL EFIAPI EfiGetCurrentTpl(VOID)
Definition: UefiLib.c:375
#define EFI_TIMER_PERIOD_SECONDS(Seconds)
Definition: UefiLib.h:98
@ TimerRelative
Definition: UefiSpec.h:539
#define USB_MASS_STORE_SCSI
SCSI transparent command set.
Definition: Usb.h:31
EFI_STATUS UsbBootGetParams(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:624
EFI_STATUS UsbBootInquiry(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:355
EFI_STATUS UsbBootExecCmd(IN USB_MASS_DEVICE *UsbMass, IN VOID *Cmd, IN UINT8 CmdLen, IN EFI_USB_DATA_DIRECTION DataDir, IN VOID *Data, IN UINT32 DataLen, IN UINT32 Timeout)
Definition: UsbMassBoot.c:170
EFI_STATUS UsbBootIsUnitReady(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:322
EFI_STATUS UsbBootReadCapacity16(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:415
EFI_STATUS UsbBootReadWriteBlocks(IN USB_MASS_DEVICE *UsbMass, IN BOOLEAN Write, IN UINT32 Lba, IN UINTN TotalBlock, IN OUT UINT8 *Buffer)
Definition: UsbMassBoot.c:810
EFI_STATUS UsbBootReadWriteBlocks16(IN USB_MASS_DEVICE *UsbMass, IN BOOLEAN Write, IN UINT64 Lba, IN UINTN TotalBlock, IN OUT UINT8 *Buffer)
Definition: UsbMassBoot.c:896
EFI_STATUS UsbBootDetectMedia(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:682
EFI_STATUS UsbBootReadCapacity(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:496
EFI_STATUS UsbClearEndpointStall(IN EFI_USB_IO_PROTOCOL *UsbIo, IN UINT8 EndpointAddr)
Definition: UsbMassBoot.c:977
EFI_STATUS UsbScsiModeSense(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:564
EFI_STATUS UsbBootExecCmdWithRetry(IN USB_MASS_DEVICE *UsbMass, IN VOID *Cmd, IN UINT8 CmdLen, IN EFI_USB_DATA_DIRECTION DataDir, IN VOID *Data, IN UINT32 DataLen, IN UINT32 Timeout)
Definition: UsbMassBoot.c:239
EFI_STATUS UsbBootRequestSense(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:26
#define USB_PDT_DIRECT_ACCESS
Direct access device.
Definition: UsbMassBoot.h:56
#define USB_BOOT_SENSE_UNIT_ATTENTION
Removable medium may have been changed.
Definition: UsbMassBoot.h:40
#define USB_BOOT_SENSE_NO_SENSE
No sense key.
Definition: UsbMassBoot.h:34
#define USB_BOOT_SENSE_NOT_READY
Device not ready.
Definition: UsbMassBoot.h:36
#define USB_PDT_OPTICAL
Non-CD optical disks.
Definition: UsbMassBoot.h:58
#define USB_PDT_CDROM
CDROM.
Definition: UsbMassBoot.h:57
#define USB_BOOT_SENSE_DATA_PROTECT
Write protected.
Definition: UsbMassBoot.h:41
#define USB_BOOT_SENSE_ILLEGAL_REQUEST
Illegal parameters in the request.
Definition: UsbMassBoot.h:39
#define USB_BOOT_SENSE_RECOVERED
Last command succeed with recovery actions.
Definition: UsbMassBoot.h:35
#define USB_PDT_SIMPLE_DIRECT
Simplified direct access device.
Definition: UsbMassBoot.h:59
USB_MASS_EXEC_COMMAND ExecCommand
Transport command to the device then get result.
Definition: UsbMass.h:163
BOOLEAN RemovableMedia
Definition: BlockIo.h:137
UINT32 LogicalBlocksPerPhysicalBlock
Definition: BlockIo.h:192
UINT32 BlockSize
Definition: BlockIo.h:167
EFI_LBA LastBlock
Definition: BlockIo.h:178
BOOLEAN MediaPresent
Definition: BlockIo.h:144
BOOLEAN ReadOnly
Definition: BlockIo.h:156
EFI_LBA LowestAlignedLba
Definition: BlockIo.h:185
UINT8 Lun
Lun (high 3 bits)
Definition: UsbMassBoot.h:94
UINT8 Lba[4]
Logical block address.
Definition: UsbMassBoot.h:153
UINT8 Lun
Lun (High 3 bits)
Definition: UsbMassBoot.h:152
UINT8 TransferLen[2]
Transfer length.
Definition: UsbMassBoot.h:155
UINT8 AllocLen
Allocation length.
Definition: UsbMassBoot.h:164
UINT8 Lun
Lun (High 3 bits)
Definition: UsbMassBoot.h:162
UINT8 Ascq
Additional Sense Code Qualifier.
Definition: UsbMassBoot.h:177
UINT8 Asc
Additional Sense Code.
Definition: UsbMassBoot.h:176
UINT8 SenseKey
Sense key (low 4 bits)
Definition: UsbMassBoot.h:172