Add DiskIo2 protocol definition to MdePkg.
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / Partition.c
CommitLineData
adbcbf8f 1/** @file\r
2 Partition driver that produces logical BlockIo devices from a physical\r
3 BlockIo device. The logical BlockIo devices are based on the format\r
4 of the raw block devices media. Currently "El Torito CD-ROM", Legacy\r
5 MBR, and GPT partition schemes are supported.\r
6\r
493d8e3a 7Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 8This program and the accompanying materials\r
f42be642 9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
adbcbf8f 12\r
f42be642 13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
adbcbf8f 15\r
16**/\r
17\r
18\r
19#include "Partition.h"\r
20\r
21//\r
ff61847d 22// Partition Driver Global Variables.\r
adbcbf8f 23//\r
24EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {\r
25 PartitionDriverBindingSupported,\r
26 PartitionDriverBindingStart,\r
27 PartitionDriverBindingStop,\r
c86b273d
RN
28 //\r
29 // Grub4Dos copies the BPB of the first partition to the MBR. If the \r
30 // DriverBindingStart() of the Fat driver gets run before that of Partition \r
31 // driver only the first partition can be recognized.\r
32 // Let the driver binding version of Partition driver be higher than that of\r
33 // Fat driver to make sure the DriverBindingStart() of the Partition driver\r
34 // gets run before that of Fat driver so that all the partitions can be recognized.\r
35 //\r
36 0xb,\r
adbcbf8f 37 NULL,\r
38 NULL\r
39};\r
40\r
ff61847d 41//\r
48557c65 42// Prioritized function list to detect partition table. \r
ff61847d 43//\r
adbcbf8f 44PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {\r
45 PartitionInstallGptChildHandles,\r
46 PartitionInstallElToritoChildHandles,\r
47 PartitionInstallMbrChildHandles,\r
48 NULL\r
49};\r
50\r
adbcbf8f 51/**\r
52 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
490b5ea1 53 than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be\r
54 supported.\r
adbcbf8f 55\r
490b5ea1 56 @param[in] This Protocol instance pointer.\r
57 @param[in] ControllerHandle Handle of device to test.\r
58 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
59 device to start.\r
adbcbf8f 60\r
61 @retval EFI_SUCCESS This driver supports this device\r
62 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
63 @retval other This driver does not support this device\r
64\r
65**/\r
66EFI_STATUS\r
67EFIAPI\r
68PartitionDriverBindingSupported (\r
69 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
70 IN EFI_HANDLE ControllerHandle,\r
71 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
72 )\r
73{\r
74 EFI_STATUS Status;\r
75 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
76 EFI_DISK_IO_PROTOCOL *DiskIo;\r
77 EFI_DEV_PATH *Node;\r
78\r
9be29006 79 //\r
80 // Check RemainingDevicePath validation\r
81 //\r
adbcbf8f 82 if (RemainingDevicePath != NULL) {\r
9be29006 83 //\r
84 // Check if RemainingDevicePath is the End of Device Path Node, \r
85 // if yes, go on checking other conditions\r
86 //\r
87 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
88 //\r
89 // If RemainingDevicePath isn't the End of Device Path Node,\r
90 // check its validation\r
91 //\r
92 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
93 if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
adbcbf8f 94 Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||\r
9be29006 95 DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {\r
490b5ea1 96 return EFI_UNSUPPORTED;\r
9be29006 97 }\r
adbcbf8f 98 }\r
99 }\r
9be29006 100\r
adbcbf8f 101 //\r
102 // Open the IO Abstraction(s) needed to perform the supported test\r
103 //\r
104 Status = gBS->OpenProtocol (\r
105 ControllerHandle,\r
9be29006 106 &gEfiDiskIoProtocolGuid,\r
107 (VOID **) &DiskIo,\r
adbcbf8f 108 This->DriverBindingHandle,\r
109 ControllerHandle,\r
110 EFI_OPEN_PROTOCOL_BY_DRIVER\r
111 );\r
112 if (Status == EFI_ALREADY_STARTED) {\r
113 return EFI_SUCCESS;\r
114 }\r
adbcbf8f 115 if (EFI_ERROR (Status)) {\r
116 return Status;\r
117 }\r
118 //\r
119 // Close the I/O Abstraction(s) used to perform the supported test\r
120 //\r
121 gBS->CloseProtocol (\r
ff61847d 122 ControllerHandle,\r
9be29006 123 &gEfiDiskIoProtocolGuid,\r
ff61847d 124 This->DriverBindingHandle,\r
125 ControllerHandle\r
126 );\r
adbcbf8f 127\r
128 //\r
9be29006 129 // Open the EFI Device Path protocol needed to perform the supported test\r
adbcbf8f 130 //\r
131 Status = gBS->OpenProtocol (\r
132 ControllerHandle,\r
9be29006 133 &gEfiDevicePathProtocolGuid,\r
134 (VOID **) &ParentDevicePath,\r
adbcbf8f 135 This->DriverBindingHandle,\r
136 ControllerHandle,\r
137 EFI_OPEN_PROTOCOL_BY_DRIVER\r
138 );\r
139 if (Status == EFI_ALREADY_STARTED) {\r
140 return EFI_SUCCESS;\r
141 }\r
142\r
143 if (EFI_ERROR (Status)) {\r
144 return Status;\r
145 }\r
9be29006 146\r
adbcbf8f 147 //\r
9be29006 148 // Close protocol, don't use device path protocol in the Support() function\r
adbcbf8f 149 //\r
150 gBS->CloseProtocol (\r
151 ControllerHandle,\r
9be29006 152 &gEfiDevicePathProtocolGuid,\r
adbcbf8f 153 This->DriverBindingHandle,\r
154 ControllerHandle\r
155 );\r
156\r
157 //\r
158 // Open the IO Abstraction(s) needed to perform the supported test\r
159 //\r
160 Status = gBS->OpenProtocol (\r
161 ControllerHandle,\r
162 &gEfiBlockIoProtocolGuid,\r
163 NULL,\r
164 This->DriverBindingHandle,\r
165 ControllerHandle,\r
166 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
167 );\r
490b5ea1 168 if (EFI_ERROR (Status)) {\r
21e1018b 169 return Status;\r
170 }\r
171\r
490b5ea1 172 return EFI_SUCCESS; \r
adbcbf8f 173}\r
174\r
adbcbf8f 175/**\r
490b5ea1 176 Start this driver on ControllerHandle by opening a Block IO or a Block IO2\r
177 or both, and Disk IO protocol, reading Device Path, and creating a child\r
178 handle with a Disk IO and device path protocol.\r
adbcbf8f 179\r
490b5ea1 180 @param[in] This Protocol instance pointer.\r
181 @param[in] ControllerHandle Handle of device to bind driver to\r
182 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
183 device to start.\r
adbcbf8f 184\r
185 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
186 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
187 @retval other This driver does not support this device\r
188\r
189**/\r
190EFI_STATUS\r
191EFIAPI\r
192PartitionDriverBindingStart (\r
193 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
194 IN EFI_HANDLE ControllerHandle,\r
195 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
196 )\r
197{\r
198 EFI_STATUS Status;\r
199 EFI_STATUS OpenStatus;\r
200 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
490b5ea1 201 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
adbcbf8f 202 EFI_DISK_IO_PROTOCOL *DiskIo;\r
493d8e3a 203 EFI_DISK_IO2_PROTOCOL *DiskIo2;\r
adbcbf8f 204 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
205 PARTITION_DETECT_ROUTINE *Routine;\r
9afd0514 206 BOOLEAN MediaPresent;\r
15cc67e6 207 EFI_TPL OldTpl;\r
adbcbf8f 208\r
21e1018b 209 BlockIo2 = NULL;\r
15cc67e6 210 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); \r
9be29006 211 //\r
212 // Check RemainingDevicePath validation\r
213 //\r
214 if (RemainingDevicePath != NULL) {\r
215 //\r
216 // Check if RemainingDevicePath is the End of Device Path Node, \r
217 // if yes, return EFI_SUCCESS\r
218 //\r
219 if (IsDevicePathEnd (RemainingDevicePath)) {\r
15cc67e6 220 Status = EFI_SUCCESS;\r
221 goto Exit;\r
9be29006 222 }\r
223 }\r
224\r
490b5ea1 225 //\r
226 // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,\r
227 // otherwise, return error.\r
228 //\r
adbcbf8f 229 Status = gBS->OpenProtocol (\r
230 ControllerHandle,\r
231 &gEfiBlockIoProtocolGuid,\r
232 (VOID **) &BlockIo,\r
233 This->DriverBindingHandle,\r
234 ControllerHandle,\r
235 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
236 );\r
237 if (EFI_ERROR (Status)) {\r
15cc67e6 238 goto Exit;\r
adbcbf8f 239 }\r
490b5ea1 240\r
241 Status = gBS->OpenProtocol (\r
242 ControllerHandle,\r
243 &gEfiBlockIo2ProtocolGuid,\r
244 (VOID **) &BlockIo2,\r
245 This->DriverBindingHandle,\r
246 ControllerHandle,\r
493d8e3a 247 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
490b5ea1 248 );\r
493d8e3a
RN
249 if (EFI_ERROR (Status)) {\r
250 BlockIo2 = NULL;\r
251 }\r
490b5ea1 252\r
adbcbf8f 253 //\r
490b5ea1 254 // Get the Device Path Protocol on ControllerHandle's handle.\r
adbcbf8f 255 //\r
256 Status = gBS->OpenProtocol (\r
257 ControllerHandle,\r
258 &gEfiDevicePathProtocolGuid,\r
259 (VOID **) &ParentDevicePath,\r
260 This->DriverBindingHandle,\r
261 ControllerHandle,\r
262 EFI_OPEN_PROTOCOL_BY_DRIVER\r
263 );\r
264 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
15cc67e6 265 goto Exit;\r
adbcbf8f 266 }\r
267\r
493d8e3a
RN
268 //\r
269 // Get the DiskIo and DiskIo2.\r
270 //\r
adbcbf8f 271 Status = gBS->OpenProtocol (\r
272 ControllerHandle,\r
273 &gEfiDiskIoProtocolGuid,\r
274 (VOID **) &DiskIo,\r
275 This->DriverBindingHandle,\r
276 ControllerHandle,\r
277 EFI_OPEN_PROTOCOL_BY_DRIVER\r
278 );\r
279 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
280 gBS->CloseProtocol (\r
281 ControllerHandle,\r
282 &gEfiDevicePathProtocolGuid,\r
283 This->DriverBindingHandle,\r
284 ControllerHandle\r
285 );\r
15cc67e6 286 goto Exit;\r
adbcbf8f 287 }\r
288\r
289 OpenStatus = Status;\r
290\r
493d8e3a
RN
291 Status = gBS->OpenProtocol (\r
292 ControllerHandle,\r
293 &gEfiDiskIo2ProtocolGuid,\r
294 (VOID **) &DiskIo2,\r
295 This->DriverBindingHandle,\r
296 ControllerHandle,\r
297 EFI_OPEN_PROTOCOL_BY_DRIVER\r
298 );\r
299 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
300 DiskIo2 = NULL;\r
301 }\r
302\r
adbcbf8f 303 //\r
9afd0514 304 // Try to read blocks when there's media or it is removable physical partition.\r
adbcbf8f 305 //\r
9afd0514 306 Status = EFI_UNSUPPORTED;\r
307 MediaPresent = BlockIo->Media->MediaPresent;\r
308 if (BlockIo->Media->MediaPresent ||\r
309 (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {\r
adbcbf8f 310 //\r
311 // Try for GPT, then El Torito, and then legacy MBR partition types. If the\r
312 // media supports a given partition type install child handles to represent\r
313 // the partitions described by the media.\r
314 //\r
315 Routine = &mPartitionDetectRoutineTable[0];\r
316 while (*Routine != NULL) {\r
317 Status = (*Routine) (\r
318 This,\r
319 ControllerHandle,\r
320 DiskIo,\r
493d8e3a 321 DiskIo2,\r
adbcbf8f 322 BlockIo,\r
490b5ea1 323 BlockIo2,\r
adbcbf8f 324 ParentDevicePath\r
325 );\r
9afd0514 326 if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {\r
adbcbf8f 327 break;\r
328 }\r
329 Routine++;\r
330 }\r
331 }\r
332 //\r
333 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),\r
334 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the\r
335 // driver. So don't try to close them. Otherwise, we will break the dependency\r
336 // between the controller and the driver set up before.\r
337 //\r
9afd0514 338 // In the case that when the media changes on a device it will Reinstall the \r
339 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent\r
340 // reentrant call to our Start() successfully. We should leave the device open\r
341 // when this happen. The "media change" case includes either the status is\r
342 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change. \r
343 // \r
344 if (EFI_ERROR (Status) &&\r
345 !EFI_ERROR (OpenStatus) &&\r
346 Status != EFI_MEDIA_CHANGED &&\r
347 !(MediaPresent && Status == EFI_NO_MEDIA)) {\r
adbcbf8f 348 gBS->CloseProtocol (\r
349 ControllerHandle,\r
350 &gEfiDiskIoProtocolGuid,\r
351 This->DriverBindingHandle,\r
352 ControllerHandle\r
353 );\r
490b5ea1 354 //\r
355 // Close Parent BlockIO2 if has.\r
356 // \r
357 gBS->CloseProtocol (\r
358 ControllerHandle,\r
359 &gEfiBlockIo2ProtocolGuid,\r
360 This->DriverBindingHandle,\r
361 ControllerHandle\r
362 );\r
adbcbf8f 363\r
364 gBS->CloseProtocol (\r
365 ControllerHandle,\r
366 &gEfiDevicePathProtocolGuid,\r
367 This->DriverBindingHandle,\r
368 ControllerHandle\r
369 );\r
370 }\r
371\r
15cc67e6 372Exit:\r
373 gBS->RestoreTPL (OldTpl);\r
adbcbf8f 374 return Status;\r
375}\r
376\r
adbcbf8f 377/**\r
48557c65 378 Stop this driver on ControllerHandle. Support stopping any child handles\r
adbcbf8f 379 created by this driver.\r
380\r
381 @param This Protocol instance pointer.\r
382 @param ControllerHandle Handle of device to stop driver on\r
383 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
384 children is zero stop the entire bus driver.\r
385 @param ChildHandleBuffer List of Child Handles to Stop.\r
386\r
387 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
388 @retval other This driver was not removed from this device\r
389\r
390**/\r
391EFI_STATUS\r
392EFIAPI\r
393PartitionDriverBindingStop (\r
394 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
395 IN EFI_HANDLE ControllerHandle,\r
396 IN UINTN NumberOfChildren,\r
397 IN EFI_HANDLE *ChildHandleBuffer\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
401 UINTN Index;\r
402 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
490b5ea1 403 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
adbcbf8f 404 BOOLEAN AllChildrenStopped;\r
405 PARTITION_PRIVATE_DATA *Private;\r
406 EFI_DISK_IO_PROTOCOL *DiskIo;\r
407\r
490b5ea1 408 BlockIo = NULL;\r
409 BlockIo2 = NULL;\r
410 Private = NULL;\r
411\r
adbcbf8f 412 if (NumberOfChildren == 0) {\r
413 //\r
414 // Close the bus driver\r
415 //\r
416 gBS->CloseProtocol (\r
417 ControllerHandle,\r
418 &gEfiDiskIoProtocolGuid,\r
419 This->DriverBindingHandle,\r
420 ControllerHandle\r
421 );\r
490b5ea1 422 //\r
423 // Close Parent BlockIO2 if has.\r
424 // \r
425 gBS->CloseProtocol (\r
426 ControllerHandle,\r
493d8e3a 427 &gEfiDiskIo2ProtocolGuid,\r
490b5ea1 428 This->DriverBindingHandle,\r
429 ControllerHandle\r
430 );\r
adbcbf8f 431\r
432 gBS->CloseProtocol (\r
433 ControllerHandle,\r
434 &gEfiDevicePathProtocolGuid,\r
435 This->DriverBindingHandle,\r
436 ControllerHandle\r
437 );\r
adbcbf8f 438 return EFI_SUCCESS;\r
439 }\r
440\r
441 AllChildrenStopped = TRUE;\r
442 for (Index = 0; Index < NumberOfChildren; Index++) {\r
490b5ea1 443 gBS->OpenProtocol (\r
444 ChildHandleBuffer[Index],\r
445 &gEfiBlockIoProtocolGuid,\r
446 (VOID **) &BlockIo,\r
447 This->DriverBindingHandle,\r
448 ControllerHandle,\r
449 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
450 );\r
451 //\r
452 // Try to locate BlockIo2.\r
453 //\r
454 gBS->OpenProtocol (\r
455 ChildHandleBuffer[Index],\r
456 &gEfiBlockIo2ProtocolGuid,\r
457 (VOID **) &BlockIo2,\r
458 This->DriverBindingHandle,\r
459 ControllerHandle,\r
460 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
461 ); \r
462\r
d0844d13 463\r
464 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
adbcbf8f 465\r
490b5ea1 466 Status = gBS->CloseProtocol (\r
467 ControllerHandle,\r
468 &gEfiDiskIoProtocolGuid,\r
469 This->DriverBindingHandle,\r
470 ChildHandleBuffer[Index]\r
471 );\r
472 //\r
473 // All Software protocols have be freed from the handle so remove it.\r
474 // Remove the BlockIo Protocol if has.\r
475 // Remove the BlockIo2 Protocol if has.\r
476 //\r
477 if (BlockIo2 != NULL) {\r
adbcbf8f 478 BlockIo->FlushBlocks (BlockIo);\r
490b5ea1 479 BlockIo2->FlushBlocksEx (BlockIo2, NULL);\r
adbcbf8f 480 Status = gBS->UninstallMultipleProtocolInterfaces (\r
490b5ea1 481 ChildHandleBuffer[Index],\r
482 &gEfiDevicePathProtocolGuid,\r
483 Private->DevicePath,\r
484 &gEfiBlockIoProtocolGuid,\r
485 &Private->BlockIo,\r
486 &gEfiBlockIo2ProtocolGuid,\r
487 &Private->BlockIo2,\r
488 Private->EspGuid,\r
489 NULL,\r
490 NULL\r
491 );\r
492 } else {\r
493 BlockIo->FlushBlocks (BlockIo);\r
494 Status = gBS->UninstallMultipleProtocolInterfaces (\r
495 ChildHandleBuffer[Index],\r
496 &gEfiDevicePathProtocolGuid,\r
497 Private->DevicePath,\r
498 &gEfiBlockIoProtocolGuid,\r
499 &Private->BlockIo,\r
500 Private->EspGuid,\r
501 NULL,\r
502 NULL\r
503 );\r
504 }\r
adbcbf8f 505\r
490b5ea1 506 if (EFI_ERROR (Status)) {\r
507 gBS->OpenProtocol (\r
508 ControllerHandle,\r
509 &gEfiDiskIoProtocolGuid,\r
510 (VOID **) &DiskIo,\r
511 This->DriverBindingHandle,\r
512 ChildHandleBuffer[Index],\r
513 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
514 );\r
515 } else {\r
516 FreePool (Private->DevicePath);\r
517 FreePool (Private);\r
adbcbf8f 518 }\r
519\r
520 if (EFI_ERROR (Status)) {\r
521 AllChildrenStopped = FALSE;\r
522 }\r
523 }\r
524\r
525 if (!AllChildrenStopped) {\r
526 return EFI_DEVICE_ERROR;\r
527 }\r
528\r
529 return EFI_SUCCESS;\r
530}\r
531\r
532\r
533/**\r
534 Reset the Block Device.\r
535\r
536 @param This Protocol instance pointer.\r
537 @param ExtendedVerification Driver may perform diagnostics on reset.\r
538\r
539 @retval EFI_SUCCESS The device was reset.\r
540 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
541 not be reset.\r
542\r
543**/\r
adbcbf8f 544EFI_STATUS\r
545EFIAPI\r
546PartitionReset (\r
547 IN EFI_BLOCK_IO_PROTOCOL *This,\r
548 IN BOOLEAN ExtendedVerification\r
549 )\r
550{\r
551 PARTITION_PRIVATE_DATA *Private;\r
552\r
553 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
554\r
555 return Private->ParentBlockIo->Reset (\r
556 Private->ParentBlockIo,\r
557 ExtendedVerification\r
558 );\r
559}\r
560\r
fcf5e49d
RN
561/**\r
562 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED\r
563 for no media or media change case. Otherwise DefaultStatus is returned.\r
564\r
565 @param DiskIo Pointer to the DiskIo instance.\r
566 @param MediaId Id of the media, changes every time the media is replaced.\r
567 @param DefaultStatus The default status to return when it's not the no media\r
568 or media change case.\r
569\r
570 @retval EFI_NO_MEDIA There is no media.\r
571 @retval EFI_MEDIA_CHANGED The media was changed.\r
572 @retval others The default status to return.\r
573**/\r
574EFI_STATUS\r
575ProbeMediaStatus (\r
576 IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
577 IN UINT32 MediaId,\r
578 IN EFI_STATUS DefaultStatus\r
579 )\r
580{\r
581 EFI_STATUS Status;\r
582\r
583 //\r
584 // Read 1 byte from offset 0 but passing NULL as buffer pointer\r
585 //\r
586 Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, NULL);\r
587 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {\r
588 return Status;\r
589 }\r
590 return DefaultStatus;\r
591}\r
adbcbf8f 592\r
593/**\r
594 Read by using the Disk IO protocol on the parent device. Lba addresses\r
595 must be converted to byte offsets.\r
596\r
597 @param This Protocol instance pointer.\r
598 @param MediaId Id of the media, changes every time the media is replaced.\r
599 @param Lba The starting Logical Block Address to read from\r
600 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
601 @param Buffer Buffer containing read data\r
602\r
603 @retval EFI_SUCCESS The data was read correctly from the device.\r
604 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
605 @retval EFI_NO_MEDIA There is no media in the device.\r
606 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
607 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
608 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not\r
609 valid for the device.\r
610\r
611**/\r
adbcbf8f 612EFI_STATUS\r
613EFIAPI\r
614PartitionReadBlocks (\r
615 IN EFI_BLOCK_IO_PROTOCOL *This,\r
616 IN UINT32 MediaId,\r
617 IN EFI_LBA Lba,\r
618 IN UINTN BufferSize,\r
619 OUT VOID *Buffer\r
620 )\r
621{\r
622 PARTITION_PRIVATE_DATA *Private;\r
623 UINT64 Offset;\r
624\r
625 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
626\r
627 if (BufferSize % Private->BlockSize != 0) {\r
fcf5e49d 628 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);\r
adbcbf8f 629 }\r
630\r
631 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
632 if (Offset + BufferSize > Private->End) {\r
fcf5e49d 633 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);\r
adbcbf8f 634 }\r
635 //\r
636 // Because some kinds of partition have different block size from their parent\r
637 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
638 // protocol\r
639 //\r
640 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
641}\r
642\r
643/**\r
644 Write by using the Disk IO protocol on the parent device. Lba addresses\r
645 must be converted to byte offsets.\r
646\r
490b5ea1 647 @param[in] This Protocol instance pointer.\r
648 @param[in] MediaId Id of the media, changes every time the media is replaced.\r
649 @param[in] Lba The starting Logical Block Address to read from\r
650 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
651 @param[in] Buffer Buffer containing data to be written to device.\r
adbcbf8f 652\r
653 @retval EFI_SUCCESS The data was written correctly to the device.\r
654 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
655 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
656 @retval EFI_NO_MEDIA There is no media in the device.\r
657 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
658 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
659 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not\r
660 valid for the device.\r
661\r
662**/\r
adbcbf8f 663EFI_STATUS\r
664EFIAPI\r
665PartitionWriteBlocks (\r
666 IN EFI_BLOCK_IO_PROTOCOL *This,\r
667 IN UINT32 MediaId,\r
668 IN EFI_LBA Lba,\r
669 IN UINTN BufferSize,\r
490b5ea1 670 IN VOID *Buffer\r
adbcbf8f 671 )\r
672{\r
673 PARTITION_PRIVATE_DATA *Private;\r
674 UINT64 Offset;\r
675\r
676 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
677\r
678 if (BufferSize % Private->BlockSize != 0) {\r
fcf5e49d 679 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);\r
adbcbf8f 680 }\r
681\r
682 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
683 if (Offset + BufferSize > Private->End) {\r
fcf5e49d 684 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);\r
adbcbf8f 685 }\r
686 //\r
687 // Because some kinds of partition have different block size from their parent\r
688 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
689 // protocol\r
690 //\r
691 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
692}\r
693\r
694\r
695/**\r
696 Flush the parent Block Device.\r
697\r
698 @param This Protocol instance pointer.\r
699\r
700 @retval EFI_SUCCESS All outstanding data was written to the device\r
701 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
702 @retval EFI_NO_MEDIA There is no media in the device.\r
703\r
704**/\r
adbcbf8f 705EFI_STATUS\r
706EFIAPI\r
707PartitionFlushBlocks (\r
708 IN EFI_BLOCK_IO_PROTOCOL *This\r
709 )\r
710{\r
711 PARTITION_PRIVATE_DATA *Private;\r
712\r
713 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
714\r
715 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
716}\r
717\r
65fd3952
RN
718/**\r
719 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED\r
720 for no media or media change case. Otherwise DefaultStatus is returned.\r
721\r
493d8e3a 722 @param DiskIo2 Pointer to the DiskIo2 instance.\r
65fd3952
RN
723 @param MediaId Id of the media, changes every time the media is replaced.\r
724 @param DefaultStatus The default status to return when it's not the no media\r
725 or media change case.\r
726\r
727 @retval EFI_NO_MEDIA There is no media.\r
728 @retval EFI_MEDIA_CHANGED The media was changed.\r
729 @retval others The default status to return.\r
730**/\r
731EFI_STATUS\r
732ProbeMediaStatusEx (\r
493d8e3a 733 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,\r
65fd3952
RN
734 IN UINT32 MediaId,\r
735 IN EFI_STATUS DefaultStatus\r
736 )\r
737{\r
738 EFI_STATUS Status;\r
739\r
740 //\r
493d8e3a 741 // Read 1 byte from offset 0 but passing NULL as buffer pointer\r
65fd3952 742 //\r
493d8e3a 743 Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL);\r
65fd3952
RN
744 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {\r
745 return Status;\r
746 }\r
747 return DefaultStatus;\r
748}\r
749\r
490b5ea1 750/**\r
751 Reset the Block Device throught Block I/O2 protocol.\r
752\r
753 @param This Protocol instance pointer.\r
754 @param ExtendedVerification Driver may perform diagnostics on reset.\r
755\r
756 @retval EFI_SUCCESS The device was reset.\r
757 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
758 not be reset.\r
759\r
760**/\r
761EFI_STATUS\r
762EFIAPI\r
763PartitionResetEx (\r
764 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
765 IN BOOLEAN ExtendedVerification\r
766 )\r
767{\r
768 PARTITION_PRIVATE_DATA *Private;\r
769\r
770 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
771\r
772 return Private->ParentBlockIo2->Reset (\r
773 Private->ParentBlockIo2,\r
774 ExtendedVerification\r
775 );\r
776}\r
777\r
493d8e3a
RN
778/**\r
779 The general callback for the DiskIo2 interfaces.\r
780 @param Event Event whose notification function is being invoked.\r
781 @param Context The pointer to the notification function's context,\r
782 which points to the PARTITION_ACCESS_TASK instance.\r
783**/\r
784VOID\r
785EFIAPI\r
786PartitionOnAccessComplete (\r
787 IN EFI_EVENT Event,\r
788 IN VOID *Context\r
789 )\r
790{\r
791 PARTITION_ACCESS_TASK *Task;\r
792\r
793 Task = (PARTITION_ACCESS_TASK *) Context;\r
794\r
795 gBS->CloseEvent (Event);\r
796\r
797 Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;\r
798 gBS->SignalEvent (Task->BlockIo2Token->Event);\r
799\r
800 FreePool (Task);\r
801}\r
802\r
803/**\r
804 Create a new PARTITION_ACCESS_TASK instance.\r
805\r
806 @param Token Pointer to the EFI_BLOCK_IO2_TOKEN.\r
807\r
808 @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.\r
809**/\r
810PARTITION_ACCESS_TASK *\r
811PartitionCreateAccessTask (\r
812 IN EFI_BLOCK_IO2_TOKEN *Token\r
813 )\r
814{\r
815 EFI_STATUS Status;\r
816 PARTITION_ACCESS_TASK *Task;\r
817\r
818 Task = AllocatePool (sizeof (*Task));\r
819 if (Task == NULL) {\r
820 return NULL;\r
821 }\r
822\r
823 Status = gBS->CreateEvent (\r
824 EVT_NOTIFY_SIGNAL,\r
825 TPL_CALLBACK,\r
826 PartitionOnAccessComplete,\r
827 Task,\r
828 &Task->DiskIo2Token.Event\r
829 );\r
830 if (EFI_ERROR (Status)) {\r
831 FreePool (Task);\r
832 return NULL;\r
833 }\r
834\r
835 Task->BlockIo2Token = Token;\r
836\r
837 return Task;\r
838}\r
839\r
490b5ea1 840/**\r
841 Read BufferSize bytes from Lba into Buffer.\r
842 \r
843 This function reads the requested number of blocks from the device. All the\r
844 blocks are read, or an error is returned.\r
845 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and\r
846 non-blocking I/O is being used, the Event associated with this request will\r
847 not be signaled.\r
848\r
849 @param[in] This Indicates a pointer to the calling context.\r
850 @param[in] MediaId Id of the media, changes every time the media is \r
851 replaced.\r
852 @param[in] Lba The starting Logical Block Address to read from.\r
853 @param[in, out] Token A pointer to the token associated with the transaction.\r
854 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. \r
855 @param[out] Buffer A pointer to the destination buffer for the data. The \r
856 caller is responsible for either having implicit or \r
857 explicit ownership of the buffer.\r
858\r
859 @retval EFI_SUCCESS The read request was queued if Token->Event is\r
860 not NULL.The data was read correctly from the\r
861 device if the Token->Event is NULL.\r
862 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
863 the read.\r
864 @retval EFI_NO_MEDIA There is no media in the device.\r
865 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
866 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
867 intrinsic block size of the device.\r
868 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
869 or the buffer is not on proper alignment.\r
870 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
871 of resources.\r
872**/\r
873EFI_STATUS\r
874EFIAPI\r
875PartitionReadBlocksEx (\r
876 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
877 IN UINT32 MediaId,\r
878 IN EFI_LBA Lba,\r
879 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
880 IN UINTN BufferSize,\r
881 OUT VOID *Buffer\r
882 )\r
883{\r
493d8e3a 884 EFI_STATUS Status;\r
490b5ea1 885 PARTITION_PRIVATE_DATA *Private;\r
886 UINT64 Offset;\r
493d8e3a 887 PARTITION_ACCESS_TASK *Task;\r
490b5ea1 888\r
65fd3952
RN
889 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
890\r
490b5ea1 891 if (BufferSize % Private->BlockSize != 0) {\r
493d8e3a 892 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);\r
490b5ea1 893 }\r
894\r
895 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
896 if (Offset + BufferSize > Private->End) {\r
493d8e3a 897 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);\r
490b5ea1 898 }\r
899\r
493d8e3a
RN
900 if ((Token != NULL) && (Token->Event != NULL)) {\r
901 Task = PartitionCreateAccessTask (Token);\r
902 if (Task == NULL) {\r
903 return EFI_OUT_OF_RESOURCES;\r
904 }\r
490b5ea1 905\r
493d8e3a
RN
906 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);\r
907 if (EFI_ERROR (Status)) {\r
908 gBS->CloseEvent (Task->DiskIo2Token.Event);\r
909 FreePool (Task);\r
910 }\r
911 } else {\r
912 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);\r
490b5ea1 913 }\r
914\r
493d8e3a 915 return Status;\r
490b5ea1 916}\r
917\r
918/**\r
919 Write BufferSize bytes from Lba into Buffer.\r
920\r
921 This function writes the requested number of blocks to the device. All blocks\r
922 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,\r
923 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is\r
924 being used, the Event associated with this request will not be signaled.\r
925\r
926 @param[in] This Indicates a pointer to the calling context.\r
927 @param[in] MediaId The media ID that the write request is for.\r
928 @param[in] Lba The starting logical block address to be written. The\r
929 caller is responsible for writing to only legitimate\r
930 locations.\r
931 @param[in, out] Token A pointer to the token associated with the transaction.\r
932 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
933 @param[in] Buffer A pointer to the source buffer for the data.\r
934\r
935 @retval EFI_SUCCESS The write request was queued if Event is not NULL.\r
936 The data was written correctly to the device if\r
937 the Event is NULL.\r
938 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
939 @retval EFI_NO_MEDIA There is no media in the device.\r
940 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
941 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
942 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
943 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
944 or the buffer is not on proper alignment.\r
945 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
946 of resources.\r
947\r
948**/\r
949EFI_STATUS\r
950EFIAPI\r
951PartitionWriteBlocksEx (\r
952 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
953 IN UINT32 MediaId,\r
954 IN EFI_LBA Lba,\r
955 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
956 IN UINTN BufferSize,\r
957 IN VOID *Buffer\r
958 )\r
959{\r
493d8e3a 960 EFI_STATUS Status;\r
490b5ea1 961 PARTITION_PRIVATE_DATA *Private;\r
962 UINT64 Offset;\r
493d8e3a 963 PARTITION_ACCESS_TASK *Task;\r
490b5ea1 964\r
65fd3952
RN
965 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
966\r
490b5ea1 967 if (BufferSize % Private->BlockSize != 0) {\r
493d8e3a 968 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);\r
490b5ea1 969 }\r
970\r
971 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
972 if (Offset + BufferSize > Private->End) {\r
493d8e3a 973 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);\r
490b5ea1 974 }\r
493d8e3a
RN
975 \r
976 if ((Token != NULL) && (Token->Event != NULL)) {\r
977 Task = PartitionCreateAccessTask (Token);\r
978 if (Task == NULL) {\r
979 return EFI_OUT_OF_RESOURCES;\r
980 }\r
490b5ea1 981\r
493d8e3a
RN
982 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);\r
983 if (EFI_ERROR (Status)) {\r
984 gBS->CloseEvent (Task->DiskIo2Token.Event);\r
985 FreePool (Task);\r
986 }\r
987 } else {\r
988 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);\r
490b5ea1 989 }\r
493d8e3a 990 return Status;\r
490b5ea1 991}\r
992\r
993/**\r
994 Flush the Block Device.\r
995 \r
996 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED\r
997 is returned and non-blocking I/O is being used, the Event associated with\r
998 this request will not be signaled. \r
999\r
1000 @param[in] This Indicates a pointer to the calling context.\r
86d8e199 1001 @param[in, out] Token A pointer to the token associated with the transaction\r
490b5ea1 1002\r
1003 @retval EFI_SUCCESS The flush request was queued if Event is not NULL.\r
1004 All outstanding data was written correctly to the\r
1005 device if the Event is NULL.\r
1006 @retval EFI_DEVICE_ERROR The device reported an error while writting back\r
1007 the data.\r
1008 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
1009 @retval EFI_NO_MEDIA There is no media in the device.\r
1010 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
1011 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
1012 of resources.\r
1013\r
1014**/\r
1015EFI_STATUS\r
1016EFIAPI\r
1017PartitionFlushBlocksEx (\r
1018 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
1019 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
1020 )\r
1021{\r
493d8e3a 1022 EFI_STATUS Status;\r
490b5ea1 1023 PARTITION_PRIVATE_DATA *Private;\r
493d8e3a 1024 PARTITION_ACCESS_TASK *Task;\r
490b5ea1 1025\r
1026 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
1027\r
493d8e3a
RN
1028 if ((Token != NULL) && (Token->Event != NULL)) {\r
1029 Task = PartitionCreateAccessTask (Token);\r
1030 if (Task == NULL) {\r
1031 return EFI_OUT_OF_RESOURCES;\r
1032 }\r
490b5ea1 1033\r
493d8e3a
RN
1034 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);\r
1035 if (EFI_ERROR (Status)) {\r
1036 gBS->CloseEvent (Task->DiskIo2Token.Event);\r
1037 FreePool (Task);\r
1038 }\r
1039 } else {\r
1040 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);\r
1041 }\r
1042 return Status;\r
490b5ea1 1043}\r
adbcbf8f 1044\r
1045\r
1046/**\r
1047 Create a child handle for a logical block device that represents the\r
1048 bytes Start to End of the Parent Block IO device.\r
1049\r
490b5ea1 1050 @param[in] This Protocol instance pointer.\r
1051 @param[in] ParentHandle Parent Handle for new child.\r
1052 @param[in] ParentDiskIo Parent DiskIo interface.\r
493d8e3a 1053 @param[in] ParentDiskIo2 Parent DiskIo2 interface.\r
490b5ea1 1054 @param[in] ParentBlockIo Parent BlockIo interface.\r
1055 @param[in] ParentBlockIo2 Parent BlockIo2 interface.\r
1056 @param[in] ParentDevicePath Parent Device Path.\r
1057 @param[in] DevicePathNode Child Device Path node.\r
1058 @param[in] Start Start Block.\r
1059 @param[in] End End Block.\r
1060 @param[in] BlockSize Child block size.\r
1061 @param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle.\r
1062\r
1063 @retval EFI_SUCCESS A child handle was added.\r
1064 @retval other A child handle was not added.\r
adbcbf8f 1065\r
1066**/\r
1067EFI_STATUS\r
1068PartitionInstallChildHandle (\r
1069 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1070 IN EFI_HANDLE ParentHandle,\r
1071 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,\r
493d8e3a 1072 IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2,\r
adbcbf8f 1073 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,\r
490b5ea1 1074 IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,\r
adbcbf8f 1075 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
1076 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,\r
1077 IN EFI_LBA Start,\r
1078 IN EFI_LBA End,\r
1079 IN UINT32 BlockSize,\r
1080 IN BOOLEAN InstallEspGuid\r
1081 )\r
1082{\r
1083 EFI_STATUS Status;\r
1084 PARTITION_PRIVATE_DATA *Private;\r
1085\r
490b5ea1 1086 Status = EFI_SUCCESS;\r
adbcbf8f 1087 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
1088 if (Private == NULL) {\r
1089 return EFI_OUT_OF_RESOURCES;\r
1090 }\r
1091\r
1092 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;\r
1093\r
1094 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
1095 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
1096\r
1097 Private->BlockSize = BlockSize;\r
1098 Private->ParentBlockIo = ParentBlockIo;\r
490b5ea1 1099 Private->ParentBlockIo2 = ParentBlockIo2;\r
adbcbf8f 1100 Private->DiskIo = ParentDiskIo;\r
493d8e3a 1101 Private->DiskIo2 = ParentDiskIo2;\r
adbcbf8f 1102\r
d0844d13 1103 //\r
1104 // Set the BlockIO into Private Data.\r
1105 //\r
1106 Private->BlockIo.Revision = ParentBlockIo->Revision;\r
1107 \r
1108 Private->BlockIo.Media = &Private->Media;\r
1109 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
490b5ea1 1110\r
d0844d13 1111 Private->BlockIo.Reset = PartitionReset;\r
1112 Private->BlockIo.ReadBlocks = PartitionReadBlocks;\r
1113 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;\r
1114 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;\r
490b5ea1 1115\r
d0844d13 1116 //\r
1117 // Set the BlockIO2 into Private Data.\r
1118 //\r
493d8e3a
RN
1119 if (Private->DiskIo2 != NULL) {\r
1120 ASSERT (Private->ParentBlockIo2 != NULL);\r
490b5ea1 1121 Private->BlockIo2.Media = &Private->Media2;\r
1122 CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
1123\r
1124 Private->BlockIo2.Reset = PartitionResetEx;\r
1125 Private->BlockIo2.ReadBlocksEx = PartitionReadBlocksEx;\r
1126 Private->BlockIo2.WriteBlocksEx = PartitionWriteBlocksEx;\r
1127 Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx; \r
1128 }\r
67f802ed 1129\r
67f802ed 1130 Private->Media.IoAlign = 0;\r
490b5ea1 1131 Private->Media.LogicalPartition = TRUE;\r
adbcbf8f 1132 Private->Media.LastBlock = DivU64x32 (\r
1133 MultU64x32 (\r
1134 End - Start + 1,\r
d0844d13 1135 ParentBlockIo->Media->BlockSize\r
adbcbf8f 1136 ),\r
490b5ea1 1137 BlockSize\r
adbcbf8f 1138 ) - 1;\r
1139\r
67f802ed 1140 Private->Media.BlockSize = (UINT32) BlockSize;\r
adbcbf8f 1141\r
493d8e3a 1142 Private->Media2.IoAlign = 0;\r
490b5ea1 1143 Private->Media2.LogicalPartition = TRUE;\r
1144 Private->Media2.LastBlock = Private->Media.LastBlock;\r
1145 Private->Media2.BlockSize = (UINT32) BlockSize;\r
1146\r
fe3b68bb 1147 //\r
0e87144e 1148 // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0\r
fe3b68bb
RN
1149 // for logical partitions.\r
1150 //\r
1151 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {\r
c582ad45
EB
1152 Private->Media.LowestAlignedLba = 0;\r
1153 Private->Media.LogicalBlocksPerPhysicalBlock = 0;\r
1154 Private->Media2.LowestAlignedLba = 0;\r
1155 Private->Media2.LogicalBlocksPerPhysicalBlock = 0;\r
0e87144e 1156 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {\r
c582ad45
EB
1157 Private->Media.OptimalTransferLengthGranularity = 0;\r
1158 Private->Media2.OptimalTransferLengthGranularity = 0;\r
0e87144e 1159 }\r
fe3b68bb
RN
1160 }\r
1161\r
490b5ea1 1162 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
adbcbf8f 1163\r
1164 if (Private->DevicePath == NULL) {\r
1165 FreePool (Private);\r
1166 return EFI_OUT_OF_RESOURCES;\r
1167 }\r
1168\r
1169 if (InstallEspGuid) {\r
1170 Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
1171 } else {\r
1172 //\r
1173 // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
1174 //\r
1175 Private->EspGuid = NULL;\r
1176 }\r
490b5ea1 1177\r
adbcbf8f 1178 //\r
490b5ea1 1179 // Create the new handle. \r
adbcbf8f 1180 //\r
1181 Private->Handle = NULL;\r
493d8e3a 1182 if (Private->DiskIo2 != NULL) {\r
490b5ea1 1183 Status = gBS->InstallMultipleProtocolInterfaces (\r
1184 &Private->Handle,\r
1185 &gEfiDevicePathProtocolGuid,\r
1186 Private->DevicePath,\r
1187 &gEfiBlockIoProtocolGuid,\r
1188 &Private->BlockIo,\r
1189 &gEfiBlockIo2ProtocolGuid,\r
1190 &Private->BlockIo2,\r
1191 Private->EspGuid,\r
1192 NULL,\r
1193 NULL\r
1194 );\r
d0844d13 1195 } else { \r
1196 Status = gBS->InstallMultipleProtocolInterfaces (\r
1197 &Private->Handle,\r
1198 &gEfiDevicePathProtocolGuid,\r
1199 Private->DevicePath,\r
1200 &gEfiBlockIoProtocolGuid,\r
1201 &Private->BlockIo,\r
1202 Private->EspGuid,\r
1203 NULL,\r
1204 NULL\r
1205 );\r
490b5ea1 1206 }\r
adbcbf8f 1207\r
1208 if (!EFI_ERROR (Status)) {\r
1209 //\r
1210 // Open the Parent Handle for the child\r
1211 //\r
1212 Status = gBS->OpenProtocol (\r
1213 ParentHandle,\r
1214 &gEfiDiskIoProtocolGuid,\r
1215 (VOID **) &ParentDiskIo,\r
1216 This->DriverBindingHandle,\r
1217 Private->Handle,\r
1218 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1219 );\r
1220 } else {\r
1221 FreePool (Private->DevicePath);\r
1222 FreePool (Private);\r
1223 }\r
1224\r
1225 return Status;\r
1226}\r
1227\r
1228\r
1229/**\r
1230 The user Entry Point for module Partition. The user code starts with this function.\r
1231\r
1232 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
1233 @param[in] SystemTable A pointer to the EFI System Table.\r
1234 \r
1235 @retval EFI_SUCCESS The entry point is executed successfully.\r
1236 @retval other Some error occurs when executing this entry point.\r
1237\r
1238**/\r
1239EFI_STATUS\r
1240EFIAPI\r
1241InitializePartition (\r
1242 IN EFI_HANDLE ImageHandle,\r
1243 IN EFI_SYSTEM_TABLE *SystemTable\r
1244 )\r
1245{\r
1246 EFI_STATUS Status;\r
1247\r
1248 //\r
1249 // Install driver model protocol(s).\r
1250 //\r
d38a0f44 1251 Status = EfiLibInstallDriverBindingComponentName2 (\r
adbcbf8f 1252 ImageHandle,\r
1253 SystemTable,\r
1254 &gPartitionDriverBinding,\r
1255 ImageHandle,\r
1256 &gPartitionComponentName,\r
d38a0f44 1257 &gPartitionComponentName2\r
adbcbf8f 1258 );\r
1259 ASSERT_EFI_ERROR (Status);\r
1260\r
1261\r
1262 return Status;\r
1263}\r
1264\r