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