]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c
77cee2442b4ed64da73dfc7c7cbee6cd77db9ef5
[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 EFI_STATUS
441 EFIAPI
442 PartitionReset (
443 IN EFI_BLOCK_IO_PROTOCOL *This,
444 IN BOOLEAN ExtendedVerification
445 )
446 /*++
447
448 Routine Description:
449 Reset the parent Block Device.
450
451 Arguments:
452 This - Protocol instance pointer.
453 ExtendedVerification - Driver may perform diagnostics on reset.
454
455 Returns:
456 EFI_SUCCESS - The device was reset.
457 EFI_DEVICE_ERROR - The device is not functioning properly and could
458 not be reset.
459
460 --*/
461 {
462 PARTITION_PRIVATE_DATA *Private;
463
464 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
465
466 return Private->ParentBlockIo->Reset (
467 Private->ParentBlockIo,
468 ExtendedVerification
469 );
470 }
471
472 EFI_STATUS
473 EFIAPI
474 PartitionReadBlocks (
475 IN EFI_BLOCK_IO_PROTOCOL *This,
476 IN UINT32 MediaId,
477 IN EFI_LBA Lba,
478 IN UINTN BufferSize,
479 OUT VOID *Buffer
480 )
481 /*++
482
483 Routine Description:
484 Read by using the Disk IO protocol on the parent device. Lba addresses
485 must be converted to byte offsets.
486
487 Arguments:
488 This - Protocol instance pointer.
489 MediaId - Id of the media, changes every time the media is replaced.
490 Lba - The starting Logical Block Address to read from
491 BufferSize - Size of Buffer, must be a multiple of device block size.
492 Buffer - Buffer containing read data
493
494 Returns:
495 EFI_SUCCESS - The data was read correctly from the device.
496 EFI_DEVICE_ERROR - The device reported an error while performing the read.
497 EFI_NO_MEDIA - There is no media in the device.
498 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.
499 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
500 device.
501 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
502 valid for the device.
503
504 --*/
505 {
506 PARTITION_PRIVATE_DATA *Private;
507 UINT64 Offset;
508
509 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
510
511 if (BufferSize % Private->BlockSize != 0) {
512 return EFI_BAD_BUFFER_SIZE;
513 }
514
515 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
516 if (Offset + BufferSize > Private->End) {
517 return EFI_INVALID_PARAMETER;
518 }
519 //
520 // Because some kinds of partition have different block size from their parent
521 // device, we call the Disk IO protocol on the parent device, not the Block IO
522 // protocol
523 //
524 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
525 }
526
527 EFI_STATUS
528 EFIAPI
529 PartitionWriteBlocks (
530 IN EFI_BLOCK_IO_PROTOCOL *This,
531 IN UINT32 MediaId,
532 IN EFI_LBA Lba,
533 IN UINTN BufferSize,
534 OUT VOID *Buffer
535 )
536 /*++
537
538 Routine Description:
539 Write by using the Disk IO protocol on the parent device. Lba addresses
540 must be converted to byte offsets.
541
542 Arguments:
543 This - Protocol instance pointer.
544 MediaId - Id of the media, changes every time the media is replaced.
545 Lba - The starting Logical Block Address to read from
546 BufferSize - Size of Buffer, must be a multiple of device block size.
547 Buffer - Buffer containing read data
548
549 Returns:
550 EFI_SUCCESS - The data was written correctly to the device.
551 EFI_WRITE_PROTECTED - The device can not be written to.
552 EFI_DEVICE_ERROR - The device reported an error while performing the write.
553 EFI_NO_MEDIA - There is no media in the device.
554 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
555 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
556 device.
557 EFI_INVALID_PARAMETER - The write request contains a LBA that is not
558 valid for the device.
559
560 --*/
561 {
562 PARTITION_PRIVATE_DATA *Private;
563 UINT64 Offset;
564
565 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
566
567 if (BufferSize % Private->BlockSize != 0) {
568 return EFI_BAD_BUFFER_SIZE;
569 }
570
571 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
572 if (Offset + BufferSize > Private->End) {
573 return EFI_INVALID_PARAMETER;
574 }
575 //
576 // Because some kinds of partition have different block size from their parent
577 // device, we call the Disk IO protocol on the parent device, not the Block IO
578 // protocol
579 //
580 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
581 }
582
583 EFI_STATUS
584 EFIAPI
585 PartitionFlushBlocks (
586 IN EFI_BLOCK_IO_PROTOCOL *This
587 )
588 /*++
589
590 Routine Description:
591 Flush the parent Block Device.
592
593 Arguments:
594 This - Protocol instance pointer.
595
596 Returns:
597 EFI_SUCCESS - All outstanding data was written to the device
598 EFI_DEVICE_ERROR - The device reported an error while writing back the data
599 EFI_NO_MEDIA - There is no media in the device.
600
601 --*/
602 {
603 PARTITION_PRIVATE_DATA *Private;
604
605 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
606
607 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
608 }
609
610 EFI_STATUS
611 PartitionInstallChildHandle (
612 IN EFI_DRIVER_BINDING_PROTOCOL *This,
613 IN EFI_HANDLE ParentHandle,
614 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
615 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
616 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
617 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
618 IN EFI_LBA Start,
619 IN EFI_LBA End,
620 IN UINT32 BlockSize,
621 IN BOOLEAN InstallEspGuid
622 )
623 /*++
624
625 Routine Description:
626 Create a child handle for a logical block device that represents the
627 bytes Start to End of the Parent Block IO device.
628
629 Arguments:
630 This - Calling context.
631 ParentHandle - Parent Handle for new child
632 ParentDiskIo - Parent DiskIo interface
633 ParentBlockIo - Parent BlockIo interface
634 ParentDevicePath - Parent Device Path
635 DevicePathNode - Child Device Path node
636 Start - Start Block
637 End - End Block
638 BlockSize - Child block size
639 InstallEspGuid - Flag to install EFI System Partition GUID on handle
640
641 Returns:
642 EFI_SUCCESS - If a child handle was added
643 EFI_OUT_OF_RESOURCES - A child handle was not added
644
645 --*/
646 {
647 EFI_STATUS Status;
648 PARTITION_PRIVATE_DATA *Private;
649
650 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
651 if (Private == NULL) {
652 return EFI_OUT_OF_RESOURCES;
653 }
654
655 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;
656
657 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
658 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
659
660 Private->BlockSize = BlockSize;
661 Private->ParentBlockIo = ParentBlockIo;
662 Private->DiskIo = ParentDiskIo;
663
664 Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
665
666 Private->BlockIo.Media = &Private->Media;
667 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
668 Private->Media.LogicalPartition = TRUE;
669 Private->Media.LastBlock = DivU64x32 (
670 MultU64x32 (
671 End - Start + 1,
672 ParentBlockIo->Media->BlockSize
673 ),
674 BlockSize
675 ) - 1;
676
677 Private->Media.BlockSize = (UINT32) BlockSize;
678
679 Private->BlockIo.Reset = PartitionReset;
680 Private->BlockIo.ReadBlocks = PartitionReadBlocks;
681 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
682 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
683
684 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
685
686 if (Private->DevicePath == NULL) {
687 gBS->FreePool (Private);
688 return EFI_OUT_OF_RESOURCES;
689 }
690
691 if (InstallEspGuid) {
692 Private->EspGuid = &gEfiPartTypeSystemPartGuid;
693 } else {
694 //
695 // If NULL InstallMultipleProtocolInterfaces will ignore it.
696 //
697 Private->EspGuid = NULL;
698 }
699 //
700 // Create the new handle
701 //
702 Private->Handle = NULL;
703 Status = gBS->InstallMultipleProtocolInterfaces (
704 &Private->Handle,
705 &gEfiDevicePathProtocolGuid,
706 Private->DevicePath,
707 &gEfiBlockIoProtocolGuid,
708 &Private->BlockIo,
709 Private->EspGuid,
710 NULL,
711 NULL
712 );
713
714 if (!EFI_ERROR (Status)) {
715 //
716 // Open the Parent Handle for the child
717 //
718 Status = gBS->OpenProtocol (
719 ParentHandle,
720 &gEfiDiskIoProtocolGuid,
721 (VOID **) &ParentDiskIo,
722 This->DriverBindingHandle,
723 Private->Handle,
724 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
725 );
726 } else {
727 gBS->FreePool (Private->DevicePath);
728 gBS->FreePool (Private);
729 }
730
731 return Status;
732 }