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