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