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