]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPeim.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBotPei / UsbBotPeim.c
1 /** @file
2
3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "UsbBotPeim.h"
17 #include "BotPeim.h"
18
19 //
20 // Global function
21 //
22 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
23 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
24 &gPeiUsbIoPpiGuid,
25 NotifyOnUsbIoPpi
26 };
27
28 EFI_PEI_RECOVERY_BLOCK_IO_PPI mRecoveryBlkIoPpi = {
29 BotGetNumberOfBlockDevices,
30 BotGetMediaInfo,
31 BotReadBlocks
32 };
33
34 EFI_PEI_RECOVERY_BLOCK_IO2_PPI mRecoveryBlkIo2Ppi = {
35 EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,
36 BotGetNumberOfBlockDevices2,
37 BotGetMediaInfo2,
38 BotReadBlocks2
39 };
40
41 EFI_PEI_PPI_DESCRIPTOR mPpiList[2] = {
42 {
43 EFI_PEI_PPI_DESCRIPTOR_PPI,
44 &gEfiPeiVirtualBlockIoPpiGuid,
45 NULL
46 },
47 {
48 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
49 &gEfiPeiVirtualBlockIo2PpiGuid,
50 NULL
51 }
52 };
53
54 /**
55 Detect whether the removable media is present and whether it has changed.
56
57 @param[in] PeiServices General-purpose services that are available to every
58 PEIM.
59 @param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.
60
61 @retval EFI_SUCCESS The media status is successfully checked.
62 @retval Other Failed to detect media.
63
64 **/
65 EFI_STATUS
66 PeiBotDetectMedia (
67 IN EFI_PEI_SERVICES **PeiServices,
68 IN PEI_BOT_DEVICE *PeiBotDev
69 );
70
71 /**
72 Initializes the Usb Bot.
73
74 @param FileHandle Handle of the file being invoked.
75 @param PeiServices Describes the list of possible PEI Services.
76
77 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
78 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
79
80 **/
81 EFI_STATUS
82 EFIAPI
83 PeimInitializeUsbBot (
84 IN EFI_PEI_FILE_HANDLE FileHandle,
85 IN CONST EFI_PEI_SERVICES **PeiServices
86 )
87 {
88 EFI_STATUS Status;
89 UINTN UsbIoPpiInstance;
90 EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
91 PEI_USB_IO_PPI *UsbIoPpi;
92
93 //
94 // Shadow this PEIM to run from memory
95 //
96 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
97 return EFI_SUCCESS;
98 }
99
100 //
101 // locate all usb io PPIs
102 //
103 for (UsbIoPpiInstance = 0; UsbIoPpiInstance < PEI_FAT_MAX_USB_IO_PPI; UsbIoPpiInstance++) {
104
105 Status = PeiServicesLocatePpi (
106 &gPeiUsbIoPpiGuid,
107 UsbIoPpiInstance,
108 &TempPpiDescriptor,
109 (VOID **) &UsbIoPpi
110 );
111 if (EFI_ERROR (Status)) {
112 break;
113 }
114 }
115 //
116 // Register a notify function
117 //
118 return PeiServicesNotifyPpi (&mNotifyList);
119 }
120
121 /**
122 UsbIo installation notification function.
123
124 This function finds out all the current USB IO PPIs in the system and add them
125 into private data.
126
127 @param PeiServices Indirect reference to the PEI Services Table.
128 @param NotifyDesc Address of the notification descriptor data structure.
129 @param InvokePpi Address of the PPI that was invoked.
130
131 @retval EFI_SUCCESS The function completes successfully.
132
133 **/
134 EFI_STATUS
135 EFIAPI
136 NotifyOnUsbIoPpi (
137 IN EFI_PEI_SERVICES **PeiServices,
138 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
139 IN VOID *InvokePpi
140 )
141 {
142 PEI_USB_IO_PPI *UsbIoPpi;
143
144 UsbIoPpi = (PEI_USB_IO_PPI *) InvokePpi;
145
146 InitUsbBot (PeiServices, UsbIoPpi);
147
148 return EFI_SUCCESS;
149 }
150
151 /**
152 Initialize the usb bot device.
153
154 @param[in] PeiServices General-purpose services that are available to every
155 PEIM.
156 @param[in] UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
157
158 @retval EFI_SUCCESS The usb bot device is initialized successfully.
159 @retval Other Failed to initialize media.
160
161 **/
162 EFI_STATUS
163 InitUsbBot (
164 IN EFI_PEI_SERVICES **PeiServices,
165 IN PEI_USB_IO_PPI *UsbIoPpi
166 )
167 {
168 PEI_BOT_DEVICE *PeiBotDevice;
169 EFI_STATUS Status;
170 EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
171 UINTN MemPages;
172 EFI_PHYSICAL_ADDRESS AllocateAddress;
173 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;
174 UINT8 Index;
175
176 //
177 // Check its interface
178 //
179 Status = UsbIoPpi->UsbGetInterfaceDescriptor (
180 PeiServices,
181 UsbIoPpi,
182 &InterfaceDesc
183 );
184 if (EFI_ERROR (Status)) {
185 return Status;
186 }
187 //
188 // Check if it is the BOT device we support
189 //
190 if ((InterfaceDesc->InterfaceClass != 0x08) || (InterfaceDesc->InterfaceProtocol != 0x50)) {
191
192 return EFI_NOT_FOUND;
193 }
194
195 MemPages = sizeof (PEI_BOT_DEVICE) / EFI_PAGE_SIZE + 1;
196 Status = PeiServicesAllocatePages (
197 EfiBootServicesCode,
198 MemPages,
199 &AllocateAddress
200 );
201 if (EFI_ERROR (Status)) {
202 return Status;
203 }
204
205 PeiBotDevice = (PEI_BOT_DEVICE *) ((UINTN) AllocateAddress);
206
207 PeiBotDevice->Signature = PEI_BOT_DEVICE_SIGNATURE;
208 PeiBotDevice->UsbIoPpi = UsbIoPpi;
209 PeiBotDevice->AllocateAddress = (UINTN) AllocateAddress;
210 PeiBotDevice->BotInterface = InterfaceDesc;
211
212 //
213 // Default value
214 //
215 PeiBotDevice->Media.DeviceType = UsbMassStorage;
216 PeiBotDevice->Media.BlockSize = 0x200;
217 PeiBotDevice->Media2.InterfaceType = MSG_USB_DP;
218 PeiBotDevice->Media2.BlockSize = 0x200;
219 PeiBotDevice->Media2.RemovableMedia = FALSE;
220 PeiBotDevice->Media2.ReadOnly = FALSE;
221
222 //
223 // Check its Bulk-in/Bulk-out endpoint
224 //
225 for (Index = 0; Index < 2; Index++) {
226 Status = UsbIoPpi->UsbGetEndpointDescriptor (
227 PeiServices,
228 UsbIoPpi,
229 Index,
230 &EndpointDesc
231 );
232
233 if (EFI_ERROR (Status)) {
234 return Status;
235 }
236
237 if ((EndpointDesc->EndpointAddress & 0x80) != 0) {
238 PeiBotDevice->BulkInEndpoint = EndpointDesc;
239 } else {
240 PeiBotDevice->BulkOutEndpoint = EndpointDesc;
241 }
242 }
243
244 CopyMem (
245 &(PeiBotDevice->BlkIoPpi),
246 &mRecoveryBlkIoPpi,
247 sizeof (EFI_PEI_RECOVERY_BLOCK_IO_PPI)
248 );
249 CopyMem (
250 &(PeiBotDevice->BlkIo2Ppi),
251 &mRecoveryBlkIo2Ppi,
252 sizeof (EFI_PEI_RECOVERY_BLOCK_IO2_PPI)
253 );
254 CopyMem (
255 &(PeiBotDevice->BlkIoPpiList),
256 &mPpiList[0],
257 sizeof (EFI_PEI_PPI_DESCRIPTOR)
258 );
259 CopyMem (
260 &(PeiBotDevice->BlkIo2PpiList),
261 &mPpiList[1],
262 sizeof (EFI_PEI_PPI_DESCRIPTOR)
263 );
264 PeiBotDevice->BlkIoPpiList.Ppi = &PeiBotDevice->BlkIoPpi;
265 PeiBotDevice->BlkIo2PpiList.Ppi = &PeiBotDevice->BlkIo2Ppi;
266
267 Status = PeiUsbInquiry (PeiServices, PeiBotDevice);
268 if (EFI_ERROR (Status)) {
269 return Status;
270 }
271
272 Status = PeiServicesAllocatePages (
273 EfiBootServicesCode,
274 1,
275 &AllocateAddress
276 );
277 if (EFI_ERROR (Status)) {
278 return Status;
279 }
280
281 PeiBotDevice->SensePtr = (ATAPI_REQUEST_SENSE_DATA *) ((UINTN) AllocateAddress);
282
283 Status = PeiServicesInstallPpi (&PeiBotDevice->BlkIoPpiList);
284
285 if (EFI_ERROR (Status)) {
286 return Status;
287 }
288
289 return EFI_SUCCESS;
290 }
291
292 /**
293 Gets the count of block I/O devices that one specific block driver detects.
294
295 This function is used for getting the count of block I/O devices that one
296 specific block driver detects. To the PEI ATAPI driver, it returns the number
297 of all the detected ATAPI devices it detects during the enumeration process.
298 To the PEI legacy floppy driver, it returns the number of all the legacy
299 devices it finds during its enumeration process. If no device is detected,
300 then the function will return zero.
301
302 @param[in] PeiServices General-purpose services that are available
303 to every PEIM.
304 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
305 instance.
306 @param[out] NumberBlockDevices The number of block I/O devices discovered.
307
308 @retval EFI_SUCCESS Operation performed successfully.
309
310 **/
311 EFI_STATUS
312 EFIAPI
313 BotGetNumberOfBlockDevices (
314 IN EFI_PEI_SERVICES **PeiServices,
315 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
316 OUT UINTN *NumberBlockDevices
317 )
318 {
319 //
320 // For Usb devices, this value should be always 1
321 //
322 *NumberBlockDevices = 1;
323 return EFI_SUCCESS;
324 }
325
326 /**
327 Gets a block device's media information.
328
329 This function will provide the caller with the specified block device's media
330 information. If the media changes, calling this function will update the media
331 information accordingly.
332
333 @param[in] PeiServices General-purpose services that are available to every
334 PEIM
335 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
336 @param[in] DeviceIndex Specifies the block device to which the function wants
337 to talk. Because the driver that implements Block I/O
338 PPIs will manage multiple block devices, the PPIs that
339 want to talk to a single device must specify the
340 device index that was assigned during the enumeration
341 process. This index is a number from one to
342 NumberBlockDevices.
343 @param[out] MediaInfo The media information of the specified block media.
344 The caller is responsible for the ownership of this
345 data structure.
346
347 @retval EFI_SUCCESS Media information about the specified block device
348 was obtained successfully.
349 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
350 error.
351
352 **/
353 EFI_STATUS
354 EFIAPI
355 BotGetMediaInfo (
356 IN EFI_PEI_SERVICES **PeiServices,
357 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
358 IN UINTN DeviceIndex,
359 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
360 )
361 {
362 PEI_BOT_DEVICE *PeiBotDev;
363 EFI_STATUS Status;
364
365 PeiBotDev = PEI_BOT_DEVICE_FROM_THIS (This);
366
367 //
368 // First test unit ready
369 //
370 PeiUsbTestUnitReady (
371 PeiServices,
372 PeiBotDev
373 );
374
375 Status = PeiBotDetectMedia (
376 PeiServices,
377 PeiBotDev
378 );
379
380 if (EFI_ERROR (Status)) {
381 return EFI_DEVICE_ERROR;
382 }
383
384 CopyMem (
385 MediaInfo,
386 &(PeiBotDev->Media),
387 sizeof (EFI_PEI_BLOCK_IO_MEDIA)
388 );
389
390 return EFI_SUCCESS;
391 }
392
393 /**
394 Reads the requested number of blocks from the specified block device.
395
396 The function reads the requested number of blocks from the device. All the
397 blocks are read, or an error is returned. If there is no media in the device,
398 the function returns EFI_NO_MEDIA.
399
400 @param[in] PeiServices General-purpose services that are available to
401 every PEIM.
402 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
403 @param[in] DeviceIndex Specifies the block device to which the function wants
404 to talk. Because the driver that implements Block I/O
405 PPIs will manage multiple block devices, the PPIs that
406 want to talk to a single device must specify the device
407 index that was assigned during the enumeration process.
408 This index is a number from one to NumberBlockDevices.
409 @param[in] StartLBA The starting logical block address (LBA) to read from
410 on the device
411 @param[in] BufferSize The size of the Buffer in bytes. This number must be
412 a multiple of the intrinsic block size of the device.
413 @param[out] Buffer A pointer to the destination buffer for the data.
414 The caller is responsible for the ownership of the
415 buffer.
416
417 @retval EFI_SUCCESS The data was read correctly from the device.
418 @retval EFI_DEVICE_ERROR The device reported an error while attempting
419 to perform the read operation.
420 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
421 valid, or the buffer is not properly aligned.
422 @retval EFI_NO_MEDIA There is no media in the device.
423 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
424 the intrinsic block size of the device.
425
426 **/
427 EFI_STATUS
428 EFIAPI
429 BotReadBlocks (
430 IN EFI_PEI_SERVICES **PeiServices,
431 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
432 IN UINTN DeviceIndex,
433 IN EFI_PEI_LBA StartLBA,
434 IN UINTN BufferSize,
435 OUT VOID *Buffer
436 )
437 {
438 PEI_BOT_DEVICE *PeiBotDev;
439 EFI_STATUS Status;
440 UINTN BlockSize;
441 UINTN NumberOfBlocks;
442
443 Status = EFI_SUCCESS;
444 PeiBotDev = PEI_BOT_DEVICE_FROM_THIS (This);
445
446 //
447 // Check parameters
448 //
449 if (Buffer == NULL) {
450 return EFI_INVALID_PARAMETER;
451 }
452
453 if (BufferSize == 0) {
454 return EFI_SUCCESS;
455 }
456
457 if (!PeiBotDev->Media.MediaPresent) {
458 return EFI_NO_MEDIA;
459 }
460
461 BlockSize = PeiBotDev->Media.BlockSize;
462
463 if (BufferSize % BlockSize != 0) {
464 Status = EFI_BAD_BUFFER_SIZE;
465 }
466
467 if (StartLBA > PeiBotDev->Media2.LastBlock) {
468 Status = EFI_INVALID_PARAMETER;
469 }
470
471 NumberOfBlocks = BufferSize / (PeiBotDev->Media.BlockSize);
472
473 if (Status == EFI_SUCCESS) {
474
475 Status = PeiUsbTestUnitReady (
476 PeiServices,
477 PeiBotDev
478 );
479 if (Status == EFI_SUCCESS) {
480 Status = PeiUsbRead10 (
481 PeiServices,
482 PeiBotDev,
483 Buffer,
484 StartLBA,
485 1
486 );
487 }
488 } else {
489 //
490 // To generate sense data for DetectMedia use.
491 //
492 PeiUsbTestUnitReady (
493 PeiServices,
494 PeiBotDev
495 );
496 }
497
498 if (EFI_ERROR (Status)) {
499 //
500 // if any error encountered, detect what happened to the media and
501 // update the media info accordingly.
502 //
503 Status = PeiBotDetectMedia (
504 PeiServices,
505 PeiBotDev
506 );
507 if (Status != EFI_SUCCESS) {
508 return EFI_DEVICE_ERROR;
509 }
510
511 NumberOfBlocks = BufferSize / PeiBotDev->Media.BlockSize;
512
513 if (!(PeiBotDev->Media.MediaPresent)) {
514 return EFI_NO_MEDIA;
515 }
516
517 if (BufferSize % (PeiBotDev->Media.BlockSize) != 0) {
518 return EFI_BAD_BUFFER_SIZE;
519 }
520
521 if (StartLBA > PeiBotDev->Media2.LastBlock) {
522 return EFI_INVALID_PARAMETER;
523 }
524
525 if ((StartLBA + NumberOfBlocks - 1) > PeiBotDev->Media2.LastBlock) {
526 return EFI_INVALID_PARAMETER;
527 }
528
529 Status = PeiUsbRead10 (
530 PeiServices,
531 PeiBotDev,
532 Buffer,
533 StartLBA,
534 NumberOfBlocks
535 );
536
537 switch (Status) {
538
539 case EFI_SUCCESS:
540 return EFI_SUCCESS;
541
542 default:
543 return EFI_DEVICE_ERROR;
544 }
545 } else {
546 StartLBA += 1;
547 NumberOfBlocks -= 1;
548 Buffer = (UINT8 *) Buffer + PeiBotDev->Media.BlockSize;
549
550 if (NumberOfBlocks == 0) {
551 return EFI_SUCCESS;
552 }
553
554 Status = PeiUsbRead10 (
555 PeiServices,
556 PeiBotDev,
557 Buffer,
558 StartLBA,
559 NumberOfBlocks
560 );
561 switch (Status) {
562
563 case EFI_SUCCESS:
564 return EFI_SUCCESS;
565
566 default:
567 return EFI_DEVICE_ERROR;
568
569 }
570 }
571 }
572
573 /**
574 Gets the count of block I/O devices that one specific block driver detects.
575
576 This function is used for getting the count of block I/O devices that one
577 specific block driver detects. To the PEI ATAPI driver, it returns the number
578 of all the detected ATAPI devices it detects during the enumeration process.
579 To the PEI legacy floppy driver, it returns the number of all the legacy
580 devices it finds during its enumeration process. If no device is detected,
581 then the function will return zero.
582
583 @param[in] PeiServices General-purpose services that are available
584 to every PEIM.
585 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
586 instance.
587 @param[out] NumberBlockDevices The number of block I/O devices discovered.
588
589 @retval EFI_SUCCESS Operation performed successfully.
590
591 **/
592 EFI_STATUS
593 EFIAPI
594 BotGetNumberOfBlockDevices2 (
595 IN EFI_PEI_SERVICES **PeiServices,
596 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
597 OUT UINTN *NumberBlockDevices
598 )
599 {
600 //
601 // For Usb devices, this value should be always 1
602 //
603 *NumberBlockDevices = 1;
604 return EFI_SUCCESS;
605 }
606
607 /**
608 Gets a block device's media information.
609
610 This function will provide the caller with the specified block device's media
611 information. If the media changes, calling this function will update the media
612 information accordingly.
613
614 @param[in] PeiServices General-purpose services that are available to every
615 PEIM
616 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
617 @param[in] DeviceIndex Specifies the block device to which the function wants
618 to talk. Because the driver that implements Block I/O
619 PPIs will manage multiple block devices, the PPIs that
620 want to talk to a single device must specify the
621 device index that was assigned during the enumeration
622 process. This index is a number from one to
623 NumberBlockDevices.
624 @param[out] MediaInfo The media information of the specified block media.
625 The caller is responsible for the ownership of this
626 data structure.
627
628 @retval EFI_SUCCESS Media information about the specified block device
629 was obtained successfully.
630 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
631 error.
632
633 **/
634 EFI_STATUS
635 EFIAPI
636 BotGetMediaInfo2 (
637 IN EFI_PEI_SERVICES **PeiServices,
638 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
639 IN UINTN DeviceIndex,
640 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo
641 )
642 {
643 PEI_BOT_DEVICE *PeiBotDev;
644 EFI_STATUS Status;
645
646 PeiBotDev = PEI_BOT_DEVICE2_FROM_THIS (This);
647
648 Status = BotGetMediaInfo (
649 PeiServices,
650 &PeiBotDev->BlkIoPpi,
651 DeviceIndex,
652 &PeiBotDev->Media
653 );
654
655 if (EFI_ERROR (Status)) {
656 return Status;
657 }
658
659 CopyMem (
660 MediaInfo,
661 &(PeiBotDev->Media2),
662 sizeof (EFI_PEI_BLOCK_IO2_MEDIA)
663 );
664
665 return EFI_SUCCESS;
666 }
667
668 /**
669 Reads the requested number of blocks from the specified block device.
670
671 The function reads the requested number of blocks from the device. All the
672 blocks are read, or an error is returned. If there is no media in the device,
673 the function returns EFI_NO_MEDIA.
674
675 @param[in] PeiServices General-purpose services that are available to
676 every PEIM.
677 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
678 @param[in] DeviceIndex Specifies the block device to which the function wants
679 to talk. Because the driver that implements Block I/O
680 PPIs will manage multiple block devices, the PPIs that
681 want to talk to a single device must specify the device
682 index that was assigned during the enumeration process.
683 This index is a number from one to NumberBlockDevices.
684 @param[in] StartLBA The starting logical block address (LBA) to read from
685 on the device
686 @param[in] BufferSize The size of the Buffer in bytes. This number must be
687 a multiple of the intrinsic block size of the device.
688 @param[out] Buffer A pointer to the destination buffer for the data.
689 The caller is responsible for the ownership of the
690 buffer.
691
692 @retval EFI_SUCCESS The data was read correctly from the device.
693 @retval EFI_DEVICE_ERROR The device reported an error while attempting
694 to perform the read operation.
695 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
696 valid, or the buffer is not properly aligned.
697 @retval EFI_NO_MEDIA There is no media in the device.
698 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
699 the intrinsic block size of the device.
700
701 **/
702 EFI_STATUS
703 EFIAPI
704 BotReadBlocks2 (
705 IN EFI_PEI_SERVICES **PeiServices,
706 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
707 IN UINTN DeviceIndex,
708 IN EFI_PEI_LBA StartLBA,
709 IN UINTN BufferSize,
710 OUT VOID *Buffer
711 )
712 {
713 PEI_BOT_DEVICE *PeiBotDev;
714 EFI_STATUS Status;
715
716 if (This == NULL) {
717 return EFI_INVALID_PARAMETER;
718 }
719
720 Status = EFI_SUCCESS;
721 PeiBotDev = PEI_BOT_DEVICE2_FROM_THIS (This);
722
723 Status = BotReadBlocks (
724 PeiServices,
725 &PeiBotDev->BlkIoPpi,
726 DeviceIndex,
727 StartLBA,
728 BufferSize,
729 Buffer
730 );
731
732 return Status;
733 }
734
735 /**
736 Detect whether the removable media is present and whether it has changed.
737
738 @param[in] PeiServices General-purpose services that are available to every
739 PEIM.
740 @param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.
741
742 @retval EFI_SUCCESS The media status is successfully checked.
743 @retval Other Failed to detect media.
744
745 **/
746 EFI_STATUS
747 PeiBotDetectMedia (
748 IN EFI_PEI_SERVICES **PeiServices,
749 IN PEI_BOT_DEVICE *PeiBotDev
750 )
751 {
752 EFI_STATUS Status;
753 EFI_STATUS FloppyStatus;
754 UINTN SenseCounts;
755 BOOLEAN NeedReadCapacity;
756 EFI_PHYSICAL_ADDRESS AllocateAddress;
757 ATAPI_REQUEST_SENSE_DATA *SensePtr;
758 UINTN Retry;
759
760 //
761 // if there is no media present,or media not changed,
762 // the request sense command will detect faster than read capacity command.
763 // read capacity command can be bypassed, thus improve performance.
764 //
765 SenseCounts = 0;
766 NeedReadCapacity = TRUE;
767
768 Status = PeiServicesAllocatePages (
769 EfiBootServicesCode,
770 1,
771 &AllocateAddress
772 );
773 if (EFI_ERROR (Status)) {
774 return Status;
775 }
776
777 SensePtr = PeiBotDev->SensePtr;
778 ZeroMem (SensePtr, EFI_PAGE_SIZE);
779
780 Status = PeiUsbRequestSense (
781 PeiServices,
782 PeiBotDev,
783 &SenseCounts,
784 (UINT8 *) SensePtr
785 );
786
787 if (Status == EFI_SUCCESS) {
788 //
789 // No Media
790 //
791 if (IsNoMedia (SensePtr, SenseCounts)) {
792 NeedReadCapacity = FALSE;
793 PeiBotDev->Media.MediaPresent = FALSE;
794 PeiBotDev->Media.LastBlock = 0;
795 PeiBotDev->Media2.MediaPresent = FALSE;
796 PeiBotDev->Media2.LastBlock = 0;
797 } else {
798 //
799 // Media Changed
800 //
801 if (IsMediaChange (SensePtr, SenseCounts)) {
802 PeiBotDev->Media.MediaPresent = TRUE;
803 PeiBotDev->Media2.MediaPresent = TRUE;
804 }
805 //
806 // Media Error
807 //
808 if (IsMediaError (SensePtr, SenseCounts)) {
809 //
810 // if media error encountered, make it look like no media present.
811 //
812 PeiBotDev->Media.MediaPresent = FALSE;
813 PeiBotDev->Media.LastBlock = 0;
814 PeiBotDev->Media2.MediaPresent = FALSE;
815 PeiBotDev->Media2.LastBlock = 0;
816 }
817
818 }
819
820 }
821
822 if (NeedReadCapacity) {
823 //
824 // Retry at most 4 times to detect media info
825 //
826 for (Retry = 0; Retry < 4; Retry++) {
827 switch (PeiBotDev->DeviceType) {
828 case USBCDROM:
829 Status = PeiUsbReadCapacity (
830 PeiServices,
831 PeiBotDev
832 );
833 break;
834
835 case USBFLOPPY2:
836 Status = PeiUsbReadFormattedCapacity (
837 PeiServices,
838 PeiBotDev
839 );
840 if (EFI_ERROR(Status)||
841 !PeiBotDev->Media.MediaPresent) {
842 //
843 // retry the ReadCapacity command
844 //
845 PeiBotDev->DeviceType = USBFLOPPY;
846 Status = EFI_DEVICE_ERROR;
847 }
848 break;
849
850 case USBFLOPPY:
851 Status = PeiUsbReadCapacity (
852 PeiServices,
853 PeiBotDev
854 );
855 if (EFI_ERROR (Status)) {
856 //
857 // retry the ReadFormatCapacity command
858 //
859 PeiBotDev->DeviceType = USBFLOPPY2;
860 }
861 break;
862
863 default:
864 return EFI_INVALID_PARAMETER;
865 }
866
867 SenseCounts = 0;
868 ZeroMem (SensePtr, EFI_PAGE_SIZE);
869
870 if (Status == EFI_SUCCESS) {
871 break;
872 }
873
874 FloppyStatus = PeiUsbRequestSense (
875 PeiServices,
876 PeiBotDev,
877 &SenseCounts,
878 (UINT8 *) SensePtr
879 );
880
881 //
882 // If Request Sense data failed,retry.
883 //
884 if (EFI_ERROR (FloppyStatus)) {
885 continue;
886 }
887 //
888 // No Media
889 //
890 if (IsNoMedia (SensePtr, SenseCounts)) {
891 PeiBotDev->Media.MediaPresent = FALSE;
892 PeiBotDev->Media.LastBlock = 0;
893 PeiBotDev->Media2.MediaPresent = FALSE;
894 PeiBotDev->Media2.LastBlock = 0;
895 break;
896 }
897
898 if (IsMediaError (SensePtr, SenseCounts)) {
899 //
900 // if media error encountered, make it look like no media present.
901 //
902 PeiBotDev->Media.MediaPresent = FALSE;
903 PeiBotDev->Media.LastBlock = 0;
904 PeiBotDev->Media2.MediaPresent = FALSE;
905 PeiBotDev->Media2.LastBlock = 0;
906 break;
907 }
908 }
909 //
910 // ENDFOR
911 //
912 // tell whether the readcapacity process is successful or not
913 // ("Status" variable record the latest status returned
914 // by ReadCapacity )
915 //
916 if (Status != EFI_SUCCESS) {
917 return EFI_DEVICE_ERROR;
918 }
919 }
920
921 return EFI_SUCCESS;
922 }