]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPeim.c
MdeModulePkg: Apply uncrustify changes
[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
1436aea4 15EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {\r
4b1bf81c 16 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
17 &gPeiUsbIoPpiGuid,\r
18 NotifyOnUsbIoPpi\r
19};\r
20\r
1436aea4 21EFI_PEI_RECOVERY_BLOCK_IO_PPI mRecoveryBlkIoPpi = {\r
4b1bf81c 22 BotGetNumberOfBlockDevices,\r
23 BotGetMediaInfo,\r
24 BotReadBlocks\r
25};\r
26\r
1436aea4 27EFI_PEI_RECOVERY_BLOCK_IO2_PPI mRecoveryBlkIo2Ppi = {\r
3fe5862f
FT
28 EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,\r
29 BotGetNumberOfBlockDevices2,\r
30 BotGetMediaInfo2,\r
31 BotReadBlocks2\r
32};\r
33\r
1436aea4 34EFI_PEI_PPI_DESCRIPTOR mPpiList[2] = {\r
3fe5862f
FT
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
1436aea4
MK
60 IN EFI_PEI_SERVICES **PeiServices,\r
61 IN PEI_BOT_DEVICE *PeiBotDev\r
4b1bf81c 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
1436aea4
MK
77 IN EFI_PEI_FILE_HANDLE FileHandle,\r
78 IN CONST EFI_PEI_SERVICES **PeiServices\r
4b1bf81c 79 )\r
80{\r
1436aea4
MK
81 EFI_STATUS Status;\r
82 UINTN UsbIoPpiInstance;\r
83 EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;\r
84 PEI_USB_IO_PPI *UsbIoPpi;\r
4b1bf81c 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
4b1bf81c 97 Status = PeiServicesLocatePpi (\r
1436aea4
MK
98 &gPeiUsbIoPpiGuid,\r
99 UsbIoPpiInstance,\r
100 &TempPpiDescriptor,\r
101 (VOID **)&UsbIoPpi\r
102 );\r
4b1bf81c 103 if (EFI_ERROR (Status)) {\r
104 break;\r
105 }\r
106 }\r
1436aea4 107\r
4b1bf81c 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
1436aea4
MK
130 IN EFI_PEI_SERVICES **PeiServices,\r
131 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
132 IN VOID *InvokePpi\r
4b1bf81c 133 )\r
134{\r
135 PEI_USB_IO_PPI *UsbIoPpi;\r
136\r
1436aea4 137 UsbIoPpi = (PEI_USB_IO_PPI *)InvokePpi;\r
4b1bf81c 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
1436aea4
MK
157 IN EFI_PEI_SERVICES **PeiServices,\r
158 IN PEI_USB_IO_PPI *UsbIoPpi\r
4b1bf81c 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
1436aea4
MK
173 PeiServices,\r
174 UsbIoPpi,\r
175 &InterfaceDesc\r
176 );\r
4b1bf81c 177 if (EFI_ERROR (Status)) {\r
178 return Status;\r
179 }\r
1436aea4 180\r
4b1bf81c 181 //\r
182 // Check if it is the BOT device we support\r
183 //\r
184 if ((InterfaceDesc->InterfaceClass != 0x08) || (InterfaceDesc->InterfaceProtocol != 0x50)) {\r
4b1bf81c 185 return EFI_NOT_FOUND;\r
186 }\r
187\r
188 MemPages = sizeof (PEI_BOT_DEVICE) / EFI_PAGE_SIZE + 1;\r
1436aea4
MK
189 Status = PeiServicesAllocatePages (\r
190 EfiBootServicesCode,\r
191 MemPages,\r
192 &AllocateAddress\r
193 );\r
4b1bf81c 194 if (EFI_ERROR (Status)) {\r
195 return Status;\r
196 }\r
197\r
1436aea4 198 PeiBotDevice = (PEI_BOT_DEVICE *)((UINTN)AllocateAddress);\r
4b1bf81c 199\r
200 PeiBotDevice->Signature = PEI_BOT_DEVICE_SIGNATURE;\r
201 PeiBotDevice->UsbIoPpi = UsbIoPpi;\r
1436aea4 202 PeiBotDevice->AllocateAddress = (UINTN)AllocateAddress;\r
4b1bf81c 203 PeiBotDevice->BotInterface = InterfaceDesc;\r
204\r
205 //\r
206 // Default value\r
207 //\r
1436aea4
MK
208 PeiBotDevice->Media.DeviceType = UsbMassStorage;\r
209 PeiBotDevice->Media.BlockSize = 0x200;\r
210 PeiBotDevice->Media2.InterfaceType = MSG_USB_DP;\r
211 PeiBotDevice->Media2.BlockSize = 0x200;\r
3fe5862f
FT
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
1436aea4
MK
220 PeiServices,\r
221 UsbIoPpi,\r
222 Index,\r
223 &EndpointDesc\r
224 );\r
4b1bf81c 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
1436aea4 260 Status = PeiUsbInquiry (PeiServices, PeiBotDevice);\r
4b1bf81c 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
1436aea4 274 PeiBotDevice->SensePtr = (ATAPI_REQUEST_SENSE_DATA *)((UINTN)AllocateAddress);\r
4b1bf81c 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
1436aea4
MK
307 IN EFI_PEI_SERVICES **PeiServices,\r
308 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
309 OUT UINTN *NumberBlockDevices\r
4b1bf81c 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
1436aea4
MK
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
4b1bf81c 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
1436aea4
MK
369 PeiServices,\r
370 PeiBotDev\r
371 );\r
4b1bf81c 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
1436aea4
MK
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
4b1bf81c 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
4b1bf81c 467 Status = PeiUsbTestUnitReady (\r
1436aea4
MK
468 PeiServices,\r
469 PeiBotDev\r
470 );\r
4b1bf81c 471 if (Status == EFI_SUCCESS) {\r
472 Status = PeiUsbRead10 (\r
1436aea4
MK
473 PeiServices,\r
474 PeiBotDev,\r
475 Buffer,\r
476 StartLBA,\r
477 1\r
478 );\r
4b1bf81c 479 }\r
480 } else {\r
481 //\r
482 // To generate sense data for DetectMedia use.\r
483 //\r
484 PeiUsbTestUnitReady (\r
485 PeiServices,\r
486 PeiBotDev\r
487 );\r
488 }\r
489\r
490 if (EFI_ERROR (Status)) {\r
491 //\r
492 // if any error encountered, detect what happened to the media and\r
493 // update the media info accordingly.\r
494 //\r
495 Status = PeiBotDetectMedia (\r
1436aea4
MK
496 PeiServices,\r
497 PeiBotDev\r
498 );\r
4b1bf81c 499 if (Status != EFI_SUCCESS) {\r
500 return EFI_DEVICE_ERROR;\r
501 }\r
502\r
503 NumberOfBlocks = BufferSize / PeiBotDev->Media.BlockSize;\r
504\r
505 if (!(PeiBotDev->Media.MediaPresent)) {\r
506 return EFI_NO_MEDIA;\r
507 }\r
508\r
509 if (BufferSize % (PeiBotDev->Media.BlockSize) != 0) {\r
510 return EFI_BAD_BUFFER_SIZE;\r
511 }\r
512\r
3fe5862f 513 if (StartLBA > PeiBotDev->Media2.LastBlock) {\r
4b1bf81c 514 return EFI_INVALID_PARAMETER;\r
515 }\r
516\r
3fe5862f 517 if ((StartLBA + NumberOfBlocks - 1) > PeiBotDev->Media2.LastBlock) {\r
4b1bf81c 518 return EFI_INVALID_PARAMETER;\r
519 }\r
520\r
521 Status = PeiUsbRead10 (\r
1436aea4
MK
522 PeiServices,\r
523 PeiBotDev,\r
524 Buffer,\r
525 StartLBA,\r
526 NumberOfBlocks\r
527 );\r
4b1bf81c 528\r
529 switch (Status) {\r
1436aea4
MK
530 case EFI_SUCCESS:\r
531 return EFI_SUCCESS;\r
4b1bf81c 532\r
1436aea4
MK
533 default:\r
534 return EFI_DEVICE_ERROR;\r
4b1bf81c 535 }\r
536 } else {\r
1436aea4 537 StartLBA += 1;\r
4b1bf81c 538 NumberOfBlocks -= 1;\r
1436aea4 539 Buffer = (UINT8 *)Buffer + PeiBotDev->Media.BlockSize;\r
4b1bf81c 540\r
541 if (NumberOfBlocks == 0) {\r
542 return EFI_SUCCESS;\r
543 }\r
544\r
545 Status = PeiUsbRead10 (\r
1436aea4
MK
546 PeiServices,\r
547 PeiBotDev,\r
548 Buffer,\r
549 StartLBA,\r
550 NumberOfBlocks\r
551 );\r
4b1bf81c 552 switch (Status) {\r
1436aea4
MK
553 case EFI_SUCCESS:\r
554 return EFI_SUCCESS;\r
4b1bf81c 555\r
1436aea4
MK
556 default:\r
557 return EFI_DEVICE_ERROR;\r
4b1bf81c 558 }\r
559 }\r
560}\r
561\r
3fe5862f
FT
562/**\r
563 Gets the count of block I/O devices that one specific block driver detects.\r
564\r
565 This function is used for getting the count of block I/O devices that one\r
566 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
567 of all the detected ATAPI devices it detects during the enumeration process.\r
568 To the PEI legacy floppy driver, it returns the number of all the legacy\r
569 devices it finds during its enumeration process. If no device is detected,\r
570 then the function will return zero.\r
571\r
572 @param[in] PeiServices General-purpose services that are available\r
573 to every PEIM.\r
574 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI\r
575 instance.\r
576 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
577\r
578 @retval EFI_SUCCESS Operation performed successfully.\r
579\r
580**/\r
581EFI_STATUS\r
582EFIAPI\r
583BotGetNumberOfBlockDevices2 (\r
1436aea4
MK
584 IN EFI_PEI_SERVICES **PeiServices,\r
585 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
586 OUT UINTN *NumberBlockDevices\r
3fe5862f
FT
587 )\r
588{\r
589 //\r
590 // For Usb devices, this value should be always 1\r
591 //\r
592 *NumberBlockDevices = 1;\r
593 return EFI_SUCCESS;\r
594}\r
595\r
596/**\r
597 Gets a block device's media information.\r
598\r
599 This function will provide the caller with the specified block device's media\r
600 information. If the media changes, calling this function will update the media\r
601 information accordingly.\r
602\r
603 @param[in] PeiServices General-purpose services that are available to every\r
604 PEIM\r
605 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
606 @param[in] DeviceIndex Specifies the block device to which the function wants\r
607 to talk. Because the driver that implements Block I/O\r
608 PPIs will manage multiple block devices, the PPIs that\r
609 want to talk to a single device must specify the\r
610 device index that was assigned during the enumeration\r
611 process. This index is a number from one to\r
612 NumberBlockDevices.\r
613 @param[out] MediaInfo The media information of the specified block media.\r
614 The caller is responsible for the ownership of this\r
615 data structure.\r
616\r
617 @retval EFI_SUCCESS Media information about the specified block device\r
618 was obtained successfully.\r
619 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
620 error.\r
621\r
622**/\r
623EFI_STATUS\r
624EFIAPI\r
625BotGetMediaInfo2 (\r
1436aea4
MK
626 IN EFI_PEI_SERVICES **PeiServices,\r
627 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
628 IN UINTN DeviceIndex,\r
629 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo\r
3fe5862f
FT
630 )\r
631{\r
632 PEI_BOT_DEVICE *PeiBotDev;\r
633 EFI_STATUS Status;\r
634\r
635 PeiBotDev = PEI_BOT_DEVICE2_FROM_THIS (This);\r
636\r
637 Status = BotGetMediaInfo (\r
638 PeiServices,\r
639 &PeiBotDev->BlkIoPpi,\r
640 DeviceIndex,\r
641 &PeiBotDev->Media\r
642 );\r
643\r
644 if (EFI_ERROR (Status)) {\r
645 return Status;\r
646 }\r
647\r
648 CopyMem (\r
649 MediaInfo,\r
650 &(PeiBotDev->Media2),\r
651 sizeof (EFI_PEI_BLOCK_IO2_MEDIA)\r
652 );\r
653\r
654 return EFI_SUCCESS;\r
655}\r
656\r
657/**\r
658 Reads the requested number of blocks from the specified block device.\r
659\r
660 The function reads the requested number of blocks from the device. All the\r
661 blocks are read, or an error is returned. If there is no media in the device,\r
662 the function returns EFI_NO_MEDIA.\r
663\r
664 @param[in] PeiServices General-purpose services that are available to\r
665 every PEIM.\r
666 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
667 @param[in] DeviceIndex Specifies the block device to which the function wants\r
668 to talk. Because the driver that implements Block I/O\r
669 PPIs will manage multiple block devices, the PPIs that\r
670 want to talk to a single device must specify the device\r
671 index that was assigned during the enumeration process.\r
672 This index is a number from one to NumberBlockDevices.\r
673 @param[in] StartLBA The starting logical block address (LBA) to read from\r
674 on the device\r
675 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
676 a multiple of the intrinsic block size of the device.\r
677 @param[out] Buffer A pointer to the destination buffer for the data.\r
678 The caller is responsible for the ownership of the\r
679 buffer.\r
680\r
681 @retval EFI_SUCCESS The data was read correctly from the device.\r
682 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
683 to perform the read operation.\r
684 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
685 valid, or the buffer is not properly aligned.\r
686 @retval EFI_NO_MEDIA There is no media in the device.\r
687 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
688 the intrinsic block size of the device.\r
689\r
690**/\r
691EFI_STATUS\r
692EFIAPI\r
693BotReadBlocks2 (\r
1436aea4
MK
694 IN EFI_PEI_SERVICES **PeiServices,\r
695 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
696 IN UINTN DeviceIndex,\r
697 IN EFI_PEI_LBA StartLBA,\r
698 IN UINTN BufferSize,\r
699 OUT VOID *Buffer\r
3fe5862f
FT
700 )\r
701{\r
702 PEI_BOT_DEVICE *PeiBotDev;\r
703 EFI_STATUS Status;\r
704\r
705 if (This == NULL) {\r
706 return EFI_INVALID_PARAMETER;\r
707 }\r
708\r
709 Status = EFI_SUCCESS;\r
710 PeiBotDev = PEI_BOT_DEVICE2_FROM_THIS (This);\r
711\r
712 Status = BotReadBlocks (\r
713 PeiServices,\r
714 &PeiBotDev->BlkIoPpi,\r
715 DeviceIndex,\r
716 StartLBA,\r
717 BufferSize,\r
718 Buffer\r
719 );\r
720\r
721 return Status;\r
722}\r
723\r
4b1bf81c 724/**\r
725 Detect whether the removable media is present and whether it has changed.\r
726\r
727 @param[in] PeiServices General-purpose services that are available to every\r
728 PEIM.\r
729 @param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.\r
730\r
731 @retval EFI_SUCCESS The media status is successfully checked.\r
732 @retval Other Failed to detect media.\r
733\r
734**/\r
735EFI_STATUS\r
736PeiBotDetectMedia (\r
1436aea4
MK
737 IN EFI_PEI_SERVICES **PeiServices,\r
738 IN PEI_BOT_DEVICE *PeiBotDev\r
4b1bf81c 739 )\r
740{\r
1436aea4
MK
741 EFI_STATUS Status;\r
742 EFI_STATUS FloppyStatus;\r
743 UINTN SenseCounts;\r
744 BOOLEAN NeedReadCapacity;\r
745 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
746 ATAPI_REQUEST_SENSE_DATA *SensePtr;\r
747 UINTN Retry;\r
4b1bf81c 748\r
749 //\r
750 // if there is no media present,or media not changed,\r
751 // the request sense command will detect faster than read capacity command.\r
752 // read capacity command can be bypassed, thus improve performance.\r
753 //\r
1436aea4
MK
754 SenseCounts = 0;\r
755 NeedReadCapacity = TRUE;\r
4b1bf81c 756\r
757 Status = PeiServicesAllocatePages (\r
758 EfiBootServicesCode,\r
759 1,\r
760 &AllocateAddress\r
761 );\r
762 if (EFI_ERROR (Status)) {\r
763 return Status;\r
764 }\r
765\r
766 SensePtr = PeiBotDev->SensePtr;\r
767 ZeroMem (SensePtr, EFI_PAGE_SIZE);\r
768\r
769 Status = PeiUsbRequestSense (\r
1436aea4
MK
770 PeiServices,\r
771 PeiBotDev,\r
772 &SenseCounts,\r
773 (UINT8 *)SensePtr\r
774 );\r
4b1bf81c 775\r
776 if (Status == EFI_SUCCESS) {\r
777 //\r
778 // No Media\r
779 //\r
780 if (IsNoMedia (SensePtr, SenseCounts)) {\r
1436aea4
MK
781 NeedReadCapacity = FALSE;\r
782 PeiBotDev->Media.MediaPresent = FALSE;\r
783 PeiBotDev->Media.LastBlock = 0;\r
3fe5862f
FT
784 PeiBotDev->Media2.MediaPresent = FALSE;\r
785 PeiBotDev->Media2.LastBlock = 0;\r
4b1bf81c 786 } else {\r
787 //\r
788 // Media Changed\r
789 //\r
790 if (IsMediaChange (SensePtr, SenseCounts)) {\r
3fe5862f
FT
791 PeiBotDev->Media.MediaPresent = TRUE;\r
792 PeiBotDev->Media2.MediaPresent = TRUE;\r
4b1bf81c 793 }\r
1436aea4 794\r
4b1bf81c 795 //\r
796 // Media Error\r
797 //\r
798 if (IsMediaError (SensePtr, SenseCounts)) {\r
799 //\r
800 // if media error encountered, make it look like no media present.\r
801 //\r
1436aea4
MK
802 PeiBotDev->Media.MediaPresent = FALSE;\r
803 PeiBotDev->Media.LastBlock = 0;\r
3fe5862f
FT
804 PeiBotDev->Media2.MediaPresent = FALSE;\r
805 PeiBotDev->Media2.LastBlock = 0;\r
4b1bf81c 806 }\r
4b1bf81c 807 }\r
4b1bf81c 808 }\r
809\r
810 if (NeedReadCapacity) {\r
811 //\r
812 // Retry at most 4 times to detect media info\r
813 //\r
814 for (Retry = 0; Retry < 4; Retry++) {\r
815 switch (PeiBotDev->DeviceType) {\r
1436aea4
MK
816 case USBCDROM:\r
817 Status = PeiUsbReadCapacity (\r
818 PeiServices,\r
819 PeiBotDev\r
820 );\r
821 break;\r
822\r
823 case USBFLOPPY2:\r
824 Status = PeiUsbReadFormattedCapacity (\r
825 PeiServices,\r
826 PeiBotDev\r
827 );\r
828 if (EFI_ERROR (Status) ||\r
829 !PeiBotDev->Media.MediaPresent)\r
830 {\r
831 //\r
832 // retry the ReadCapacity command\r
833 //\r
834 PeiBotDev->DeviceType = USBFLOPPY;\r
835 Status = EFI_DEVICE_ERROR;\r
836 }\r
837\r
838 break;\r
839\r
840 case USBFLOPPY:\r
841 Status = PeiUsbReadCapacity (\r
842 PeiServices,\r
843 PeiBotDev\r
844 );\r
845 if (EFI_ERROR (Status)) {\r
846 //\r
847 // retry the ReadFormatCapacity command\r
848 //\r
849 PeiBotDev->DeviceType = USBFLOPPY2;\r
850 }\r
851\r
852 break;\r
853\r
854 default:\r
855 return EFI_INVALID_PARAMETER;\r
4b1bf81c 856 }\r
857\r
858 SenseCounts = 0;\r
859 ZeroMem (SensePtr, EFI_PAGE_SIZE);\r
860\r
861 if (Status == EFI_SUCCESS) {\r
862 break;\r
863 }\r
864\r
865 FloppyStatus = PeiUsbRequestSense (\r
1436aea4
MK
866 PeiServices,\r
867 PeiBotDev,\r
868 &SenseCounts,\r
869 (UINT8 *)SensePtr\r
870 );\r
4b1bf81c 871\r
872 //\r
873 // If Request Sense data failed,retry.\r
874 //\r
875 if (EFI_ERROR (FloppyStatus)) {\r
876 continue;\r
877 }\r
1436aea4 878\r
4b1bf81c 879 //\r
880 // No Media\r
881 //\r
882 if (IsNoMedia (SensePtr, SenseCounts)) {\r
1436aea4
MK
883 PeiBotDev->Media.MediaPresent = FALSE;\r
884 PeiBotDev->Media.LastBlock = 0;\r
3fe5862f
FT
885 PeiBotDev->Media2.MediaPresent = FALSE;\r
886 PeiBotDev->Media2.LastBlock = 0;\r
4b1bf81c 887 break;\r
888 }\r
889\r
890 if (IsMediaError (SensePtr, SenseCounts)) {\r
891 //\r
892 // if media error encountered, make it look like no media present.\r
893 //\r
1436aea4
MK
894 PeiBotDev->Media.MediaPresent = FALSE;\r
895 PeiBotDev->Media.LastBlock = 0;\r
3fe5862f
FT
896 PeiBotDev->Media2.MediaPresent = FALSE;\r
897 PeiBotDev->Media2.LastBlock = 0;\r
4b1bf81c 898 break;\r
899 }\r
900 }\r
1436aea4 901\r
4b1bf81c 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