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