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