]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c
Initial import.
[mirror_edk2.git] / EdkModulePkg / Universal / Disk / Partition / Dxe / Partition.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Partition.c\r
15\r
16Abstract:\r
17\r
18 Partition driver that produces logical BlockIo devices from a physical\r
19 BlockIo device. The logical BlockIo devices are based on the format\r
20 of the raw block devices media. Currently "El Torito CD-ROM", Legacy\r
21 MBR, and GPT partition schemes are supported.\r
22\r
23--*/\r
24\r
25#include "Partition.h"\r
26\r
27//\r
28// Function Prototypes\r
29//\r
30EFI_STATUS\r
31EFIAPI\r
32PartitionEntryPoint (\r
33 IN EFI_HANDLE ImageHandle,\r
34 IN EFI_SYSTEM_TABLE *SystemTable\r
35 );\r
36\r
37EFI_STATUS\r
38EFIAPI\r
39PartitionDriverBindingSupported (\r
40 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
41 IN EFI_HANDLE ControllerHandle,\r
42 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
43 );\r
44\r
45EFI_STATUS\r
46EFIAPI\r
47PartitionDriverBindingStart (\r
48 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
49 IN EFI_HANDLE ControllerHandle,\r
50 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
51 );\r
52\r
53EFI_STATUS\r
54EFIAPI\r
55PartitionDriverBindingStop (\r
56 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
57 IN EFI_HANDLE ControllerHandle,\r
58 IN UINTN NumberOfChildren,\r
59 IN EFI_HANDLE *ChildHandleBuffer\r
60 );\r
61\r
62//\r
63// Partition Driver Global Variables\r
64//\r
65EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {\r
66 PartitionDriverBindingSupported,\r
67 PartitionDriverBindingStart,\r
68 PartitionDriverBindingStop,\r
69 0x10,\r
70 NULL,\r
71 NULL\r
72};\r
73\r
74EFI_STATUS\r
75EFIAPI\r
76PartitionDriverBindingSupported (\r
77 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
78 IN EFI_HANDLE ControllerHandle,\r
79 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
80 )\r
81/*++\r
82\r
83 Routine Description:\r
84 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
85 than contains a BlockIo and DiskIo protocol can be supported.\r
86\r
87 Arguments:\r
88 This - Protocol instance pointer.\r
89 ControllerHandle - Handle of device to test\r
90 RemainingDevicePath - Not used\r
91\r
92 Returns:\r
93 EFI_SUCCESS - This driver supports this device\r
94 EFI_ALREADY_STARTED - This driver is already running on this device\r
95 EFI_UNSUPPORTED - This driver does not support this device\r
96\r
97--*/\r
98{\r
99 EFI_STATUS Status;\r
100 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
101 EFI_DISK_IO_PROTOCOL *DiskIo;\r
102 EFI_DEV_PATH *Node;\r
103\r
104 if (RemainingDevicePath != NULL) {\r
105 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
106 if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
107 Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||\r
108 DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)\r
109 ) {\r
110 return EFI_UNSUPPORTED;\r
111 }\r
112 }\r
113 //\r
114 // Open the IO Abstraction(s) needed to perform the supported test\r
115 //\r
116 Status = gBS->OpenProtocol (\r
117 ControllerHandle,\r
118 &gEfiDevicePathProtocolGuid,\r
119 (VOID **) &ParentDevicePath,\r
120 This->DriverBindingHandle,\r
121 ControllerHandle,\r
122 EFI_OPEN_PROTOCOL_BY_DRIVER\r
123 );\r
124 if (Status == EFI_ALREADY_STARTED) {\r
125 return EFI_SUCCESS;\r
126 }\r
127\r
128 if (EFI_ERROR (Status)) {\r
129 return Status;\r
130 }\r
131 //\r
132 // Close the I/O Abstraction(s) used to perform the supported test\r
133 //\r
134 gBS->CloseProtocol (\r
135 ControllerHandle,\r
136 &gEfiDevicePathProtocolGuid,\r
137 This->DriverBindingHandle,\r
138 ControllerHandle\r
139 );\r
140\r
141 //\r
142 // Open the IO Abstraction(s) needed to perform the supported test\r
143 //\r
144 Status = gBS->OpenProtocol (\r
145 ControllerHandle,\r
146 &gEfiDiskIoProtocolGuid,\r
147 (VOID **) &DiskIo,\r
148 This->DriverBindingHandle,\r
149 ControllerHandle,\r
150 EFI_OPEN_PROTOCOL_BY_DRIVER\r
151 );\r
152 if (Status == EFI_ALREADY_STARTED) {\r
153 return EFI_SUCCESS;\r
154 }\r
155\r
156 if (EFI_ERROR (Status)) {\r
157 return Status;\r
158 }\r
159 //\r
160 // Close the I/O Abstraction(s) used to perform the supported test\r
161 //\r
162 gBS->CloseProtocol (\r
163 ControllerHandle,\r
164 &gEfiDiskIoProtocolGuid,\r
165 This->DriverBindingHandle,\r
166 ControllerHandle\r
167 );\r
168\r
169 //\r
170 // Open the IO Abstraction(s) needed to perform the supported test\r
171 //\r
172 Status = gBS->OpenProtocol (\r
173 ControllerHandle,\r
174 &gEfiBlockIoProtocolGuid,\r
175 NULL,\r
176 This->DriverBindingHandle,\r
177 ControllerHandle,\r
178 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
179 );\r
180\r
181 return Status;\r
182}\r
183\r
184EFI_STATUS\r
185EFIAPI\r
186PartitionDriverBindingStart (\r
187 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
188 IN EFI_HANDLE ControllerHandle,\r
189 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
190 )\r
191/*++\r
192\r
193 Routine Description:\r
194 Start this driver on ControllerHandle by opening a Block IO and Disk IO\r
195 protocol, reading Device Path, and creating a child handle with a\r
196 Disk IO and device path protocol.\r
197\r
198 Arguments:\r
199 This - Protocol instance pointer.\r
200 ControllerHandle - Handle of device to bind driver to\r
201 RemainingDevicePath - Not used\r
202\r
203 Returns:\r
204 EFI_SUCCESS - This driver is added to DeviceHandle\r
205 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle\r
206 other - This driver does not support this device\r
207\r
208--*/\r
209{\r
210 EFI_STATUS Status;\r
211 EFI_STATUS OpenStatus;\r
212 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
213 EFI_DISK_IO_PROTOCOL *DiskIo;\r
214 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
215\r
216 Status = gBS->OpenProtocol (\r
217 ControllerHandle,\r
218 &gEfiBlockIoProtocolGuid,\r
219 (VOID **) &BlockIo,\r
220 This->DriverBindingHandle,\r
221 ControllerHandle,\r
222 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
223 );\r
224 if (EFI_ERROR (Status)) {\r
225 return Status;\r
226 }\r
227 //\r
228 // Get the Device Path Protocol on ControllerHandle's handle\r
229 //\r
230 Status = gBS->OpenProtocol (\r
231 ControllerHandle,\r
232 &gEfiDevicePathProtocolGuid,\r
233 (VOID **) &ParentDevicePath,\r
234 This->DriverBindingHandle,\r
235 ControllerHandle,\r
236 EFI_OPEN_PROTOCOL_BY_DRIVER\r
237 );\r
238 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
239 return Status;\r
240 }\r
241\r
242 Status = gBS->OpenProtocol (\r
243 ControllerHandle,\r
244 &gEfiDiskIoProtocolGuid,\r
245 (VOID **) &DiskIo,\r
246 This->DriverBindingHandle,\r
247 ControllerHandle,\r
248 EFI_OPEN_PROTOCOL_BY_DRIVER\r
249 );\r
250 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
251 gBS->CloseProtocol (\r
252 ControllerHandle,\r
253 &gEfiDevicePathProtocolGuid,\r
254 This->DriverBindingHandle,\r
255 ControllerHandle\r
256 );\r
257 return Status;\r
258 }\r
259\r
260 OpenStatus = Status;\r
261\r
262 //\r
263 // If no media is present, do nothing here.\r
264 //\r
265 Status = EFI_UNSUPPORTED;\r
266 if (BlockIo->Media->MediaPresent) {\r
267 //\r
268 // Try for GPT, then El Torito, and then legacy MBR partition types. If the\r
269 // media supports a given partition type install child handles to represent\r
270 // the partitions described by the media.\r
271 //\r
272 if (PartitionInstallGptChildHandles (\r
273 This,\r
274 ControllerHandle,\r
275 DiskIo,\r
276 BlockIo,\r
277 ParentDevicePath\r
278 ) ||\r
279\r
280 PartitionInstallElToritoChildHandles (\r
281 This,\r
282 ControllerHandle,\r
283 DiskIo,\r
284 BlockIo,\r
285 ParentDevicePath\r
286 ) ||\r
287\r
288 PartitionInstallMbrChildHandles (\r
289 This,\r
290 ControllerHandle,\r
291 DiskIo,\r
292 BlockIo,\r
293 ParentDevicePath\r
294 )) {\r
295 Status = EFI_SUCCESS;\r
296 } else {\r
297 Status = EFI_NOT_FOUND;\r
298 }\r
299 }\r
300 //\r
301 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),\r
302 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the\r
303 // driver. So don't try to close them. Otherwise, we will break the dependency\r
304 // between the controller and the driver set up before.\r
305 //\r
306 if (EFI_ERROR (Status) && !EFI_ERROR (OpenStatus)) {\r
307 gBS->CloseProtocol (\r
308 ControllerHandle,\r
309 &gEfiDiskIoProtocolGuid,\r
310 This->DriverBindingHandle,\r
311 ControllerHandle\r
312 );\r
313\r
314 gBS->CloseProtocol (\r
315 ControllerHandle,\r
316 &gEfiDevicePathProtocolGuid,\r
317 This->DriverBindingHandle,\r
318 ControllerHandle\r
319 );\r
320 }\r
321\r
322 return Status;\r
323}\r
324\r
325EFI_STATUS\r
326EFIAPI\r
327PartitionDriverBindingStop (\r
328 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
329 IN EFI_HANDLE ControllerHandle,\r
330 IN UINTN NumberOfChildren,\r
331 IN EFI_HANDLE *ChildHandleBuffer\r
332 )\r
333/*++\r
334\r
335 Routine Description:\r
336 Stop this driver on ControllerHandle. Support stoping any child handles\r
337 created by this driver.\r
338\r
339 Arguments:\r
340 This - Protocol instance pointer.\r
341 ControllerHandle - Handle of device to stop driver on\r
342 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
343 ChildHandleBuffer - List of handles for the children we need to stop.\r
344\r
345 Returns:\r
346 EFI_SUCCESS - This driver is removed DeviceHandle\r
347 EFI_DEVICE_ERROR - This driver was not removed from this device\r
348\r
349--*/\r
350{\r
351 EFI_STATUS Status;\r
352 UINTN Index;\r
353 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
354 BOOLEAN AllChildrenStopped;\r
355 PARTITION_PRIVATE_DATA *Private;\r
356 EFI_DISK_IO_PROTOCOL *DiskIo;\r
357\r
358 if (NumberOfChildren == 0) {\r
359 //\r
360 // Close the bus driver\r
361 //\r
362 gBS->CloseProtocol (\r
363 ControllerHandle,\r
364 &gEfiDiskIoProtocolGuid,\r
365 This->DriverBindingHandle,\r
366 ControllerHandle\r
367 );\r
368\r
369 gBS->CloseProtocol (\r
370 ControllerHandle,\r
371 &gEfiDevicePathProtocolGuid,\r
372 This->DriverBindingHandle,\r
373 ControllerHandle\r
374 );\r
375\r
376 return EFI_SUCCESS;\r
377 }\r
378\r
379 AllChildrenStopped = TRUE;\r
380 for (Index = 0; Index < NumberOfChildren; Index++) {\r
381 Status = gBS->OpenProtocol (\r
382 ChildHandleBuffer[Index],\r
383 &gEfiBlockIoProtocolGuid,\r
384 (VOID **) &BlockIo,\r
385 This->DriverBindingHandle,\r
386 ControllerHandle,\r
387 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
388 );\r
389 if (!EFI_ERROR (Status)) {\r
390\r
391 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
392\r
393 //\r
394 // All Software protocols have be freed from the handle so remove it.\r
395 //\r
396 BlockIo->FlushBlocks (BlockIo);\r
397\r
398 Status = gBS->CloseProtocol (\r
399 ControllerHandle,\r
400 &gEfiDiskIoProtocolGuid,\r
401 This->DriverBindingHandle,\r
402 ChildHandleBuffer[Index]\r
403 );\r
404\r
405 Status = gBS->UninstallMultipleProtocolInterfaces (\r
406 ChildHandleBuffer[Index],\r
407 &gEfiDevicePathProtocolGuid,\r
408 Private->DevicePath,\r
409 &gEfiBlockIoProtocolGuid,\r
410 &Private->BlockIo,\r
411 Private->EspGuid,\r
412 NULL,\r
413 NULL\r
414 );\r
415 if (EFI_ERROR (Status)) {\r
416 gBS->OpenProtocol (\r
417 ControllerHandle,\r
418 &gEfiDiskIoProtocolGuid,\r
419 (VOID **) &DiskIo,\r
420 This->DriverBindingHandle,\r
421 ChildHandleBuffer[Index],\r
422 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
423 );\r
424 } else {\r
425 gBS->FreePool (Private->DevicePath);\r
426 gBS->FreePool (Private);\r
427 }\r
428\r
429 }\r
430\r
431 if (EFI_ERROR (Status)) {\r
432 AllChildrenStopped = FALSE;\r
433 }\r
434 }\r
435\r
436 if (!AllChildrenStopped) {\r
437 return EFI_DEVICE_ERROR;\r
438 }\r
439\r
440 return EFI_SUCCESS;\r
441}\r
442\r
443EFI_STATUS\r
444EFIAPI\r
445PartitionReset (\r
446 IN EFI_BLOCK_IO_PROTOCOL *This,\r
447 IN BOOLEAN ExtendedVerification\r
448 )\r
449/*++\r
450\r
451 Routine Description:\r
452 Reset the parent Block Device.\r
453\r
454 Arguments:\r
455 This - Protocol instance pointer.\r
456 ExtendedVerification - Driver may perform diagnostics on reset.\r
457\r
458 Returns:\r
459 EFI_SUCCESS - The device was reset.\r
460 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
461 not be reset.\r
462\r
463--*/\r
464{\r
465 PARTITION_PRIVATE_DATA *Private;\r
466\r
467 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
468\r
469 return Private->ParentBlockIo->Reset (\r
470 Private->ParentBlockIo,\r
471 ExtendedVerification\r
472 );\r
473}\r
474\r
475EFI_STATUS\r
476EFIAPI\r
477PartitionReadBlocks (\r
478 IN EFI_BLOCK_IO_PROTOCOL *This,\r
479 IN UINT32 MediaId,\r
480 IN EFI_LBA Lba,\r
481 IN UINTN BufferSize,\r
482 OUT VOID *Buffer\r
483 )\r
484/*++\r
485\r
486 Routine Description:\r
487 Read by using the Disk IO protocol on the parent device. Lba addresses\r
488 must be converted to byte offsets.\r
489\r
490 Arguments:\r
491 This - Protocol instance pointer.\r
492 MediaId - Id of the media, changes every time the media is replaced.\r
493 Lba - The starting Logical Block Address to read from\r
494 BufferSize - Size of Buffer, must be a multiple of device block size.\r
495 Buffer - Buffer containing read data\r
496\r
497 Returns:\r
498 EFI_SUCCESS - The data was read correctly from the device.\r
499 EFI_DEVICE_ERROR - The device reported an error while performing the read.\r
500 EFI_NO_MEDIA - There is no media in the device.\r
501 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.\r
502 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
503 device.\r
504 EFI_INVALID_PARAMETER - The read request contains device addresses that are not\r
505 valid for the device.\r
506\r
507--*/\r
508{\r
509 PARTITION_PRIVATE_DATA *Private;\r
510 UINT64 Offset;\r
511\r
512 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
513\r
514 if (BufferSize % Private->BlockSize != 0) {\r
515 return EFI_BAD_BUFFER_SIZE;\r
516 }\r
517\r
518 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
519 if (Offset + BufferSize > Private->End) {\r
520 return EFI_INVALID_PARAMETER;\r
521 }\r
522 //\r
523 // Because some kinds of partition have different block size from their parent\r
524 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
525 // protocol\r
526 //\r
527 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
528}\r
529\r
530EFI_STATUS\r
531EFIAPI\r
532PartitionWriteBlocks (\r
533 IN EFI_BLOCK_IO_PROTOCOL *This,\r
534 IN UINT32 MediaId,\r
535 IN EFI_LBA Lba,\r
536 IN UINTN BufferSize,\r
537 OUT VOID *Buffer\r
538 )\r
539/*++\r
540\r
541 Routine Description:\r
542 Write by using the Disk IO protocol on the parent device. Lba addresses\r
543 must be converted to byte offsets.\r
544\r
545 Arguments:\r
546 This - Protocol instance pointer.\r
547 MediaId - Id of the media, changes every time the media is replaced.\r
548 Lba - The starting Logical Block Address to read from\r
549 BufferSize - Size of Buffer, must be a multiple of device block size.\r
550 Buffer - Buffer containing read data\r
551\r
552 Returns:\r
553 EFI_SUCCESS - The data was written correctly to the device.\r
554 EFI_WRITE_PROTECTED - The device can not be written to.\r
555 EFI_DEVICE_ERROR - The device reported an error while performing the write.\r
556 EFI_NO_MEDIA - There is no media in the device.\r
557 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.\r
558 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
559 device.\r
560 EFI_INVALID_PARAMETER - The write request contains a LBA that is not\r
561 valid for the device.\r
562\r
563--*/\r
564{\r
565 PARTITION_PRIVATE_DATA *Private;\r
566 UINT64 Offset;\r
567\r
568 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
569\r
570 if (BufferSize % Private->BlockSize != 0) {\r
571 return EFI_BAD_BUFFER_SIZE;\r
572 }\r
573\r
574 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
575 if (Offset + BufferSize > Private->End) {\r
576 return EFI_INVALID_PARAMETER;\r
577 }\r
578 //\r
579 // Because some kinds of partition have different block size from their parent\r
580 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
581 // protocol\r
582 //\r
583 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
584}\r
585\r
586EFI_STATUS\r
587EFIAPI\r
588PartitionFlushBlocks (\r
589 IN EFI_BLOCK_IO_PROTOCOL *This\r
590 )\r
591/*++\r
592\r
593 Routine Description:\r
594 Flush the parent Block Device.\r
595\r
596 Arguments:\r
597 This - Protocol instance pointer.\r
598\r
599 Returns:\r
600 EFI_SUCCESS - All outstanding data was written to the device\r
601 EFI_DEVICE_ERROR - The device reported an error while writing back the data\r
602 EFI_NO_MEDIA - There is no media in the device.\r
603\r
604--*/\r
605{\r
606 PARTITION_PRIVATE_DATA *Private;\r
607\r
608 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
609\r
610 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
611}\r
612\r
613EFI_STATUS\r
614PartitionInstallChildHandle (\r
615 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
616 IN EFI_HANDLE ParentHandle,\r
617 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,\r
618 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,\r
619 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
620 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,\r
621 IN EFI_LBA Start,\r
622 IN EFI_LBA End,\r
623 IN UINT32 BlockSize,\r
624 IN BOOLEAN InstallEspGuid\r
625 )\r
626/*++\r
627\r
628Routine Description:\r
629 Create a child handle for a logical block device that represents the\r
630 bytes Start to End of the Parent Block IO device.\r
631\r
632Arguments:\r
633 This - Calling context.\r
634 ParentHandle - Parent Handle for new child\r
635 ParentDiskIo - Parent DiskIo interface\r
636 ParentBlockIo - Parent BlockIo interface\r
637 ParentDevicePath - Parent Device Path\r
638 DevicePathNode - Child Device Path node\r
639 Start - Start Block\r
640 End - End Block\r
641 BlockSize - Child block size\r
642 InstallEspGuid - Flag to install EFI System Partition GUID on handle\r
643\r
644Returns:\r
645 EFI_SUCCESS - If a child handle was added\r
646 EFI_OUT_OF_RESOURCES - A child handle was not added\r
647\r
648--*/\r
649{\r
650 EFI_STATUS Status;\r
651 PARTITION_PRIVATE_DATA *Private;\r
652\r
653 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
654 if (Private == NULL) {\r
655 return EFI_OUT_OF_RESOURCES;\r
656 }\r
657\r
658 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;\r
659\r
660 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
661 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
662\r
663 Private->BlockSize = BlockSize;\r
664 Private->ParentBlockIo = ParentBlockIo;\r
665 Private->DiskIo = ParentDiskIo;\r
666\r
667 Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
668\r
669 Private->BlockIo.Media = &Private->Media;\r
670 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
671 Private->Media.LogicalPartition = TRUE;\r
672 Private->Media.LastBlock = DivU64x32 (\r
673 MultU64x32 (\r
674 End - Start + 1,\r
675 ParentBlockIo->Media->BlockSize\r
676 ),\r
677 BlockSize\r
678 ) - 1;\r
679\r
680 Private->Media.BlockSize = (UINT32) BlockSize;\r
681\r
682 Private->BlockIo.Reset = PartitionReset;\r
683 Private->BlockIo.ReadBlocks = PartitionReadBlocks;\r
684 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;\r
685 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;\r
686\r
687 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
688\r
689 if (Private->DevicePath == NULL) {\r
690 gBS->FreePool (Private);\r
691 return EFI_OUT_OF_RESOURCES;\r
692 }\r
693\r
694 if (InstallEspGuid) {\r
695 Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
696 } else {\r
697 //\r
698 // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
699 //\r
700 Private->EspGuid = NULL;\r
701 }\r
702 //\r
703 // Create the new handle\r
704 //\r
705 Private->Handle = NULL;\r
706 Status = gBS->InstallMultipleProtocolInterfaces (\r
707 &Private->Handle,\r
708 &gEfiDevicePathProtocolGuid,\r
709 Private->DevicePath,\r
710 &gEfiBlockIoProtocolGuid,\r
711 &Private->BlockIo,\r
712 Private->EspGuid,\r
713 NULL,\r
714 NULL\r
715 );\r
716\r
717 if (!EFI_ERROR (Status)) {\r
718 //\r
719 // Open the Parent Handle for the child\r
720 //\r
721 Status = gBS->OpenProtocol (\r
722 ParentHandle,\r
723 &gEfiDiskIoProtocolGuid,\r
724 (VOID **) &ParentDiskIo,\r
725 This->DriverBindingHandle,\r
726 Private->Handle,\r
727 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
728 );\r
729 } else {\r
730 gBS->FreePool (Private->DevicePath);\r
731 gBS->FreePool (Private);\r
732 }\r
733\r
734 return Status;\r
735}\r